Where does this LINQ function come from?

I made a function to recursively find the first or standard element that matches the condition (first block of code).

Resharper suggested that I change several lines in only one LINQ line (second block of code).

I was wondering if the Resharper suggestion could give me the same performance and the same amount of memory. I did a performance test (3rd block of code). The result is exactly what I expected. Why is the difference so big?

8156 milliseconds
Laure
23567 milliseconds
Laure LINQ

Where does this difference come from ??? Why don't the results match? ... or at least closer?

public static T RecursiveFirstOrDefault<T>(this T item, Func<T, IEnumerable<T>> childrenSelector, Predicate<T> condition)
    where T : class // Hierarchy implies class. Don't need to play with "default()" here.
{
    if (item == null)
    {
        return null;
    }

    if (condition(item))
    {
        return item;
    }

    foreach (T child in childrenSelector(item))
    {
        T result = child.RecursiveFirstOrDefault(childrenSelector, condition);
        if (result != null)
        {
            return result;
        }
    }

    return null;
}

But Resharper suggested that I convert the foreach block to a LINQ query as follows:

public static T RecursiveFirstOrDefaultLinq<T>(this T item, Func<T, IEnumerable<T>> childrenSelector, Predicate<T> condition)
    where T : class // Hierarchy implies class. Don't need to play with "default()" here.
{
    if (item == null)
    {
        return null;
    }

    if (condition(item))
    {
        return item;
    }

    // Resharper change:
    return childrenSelector(item).Select(child => child.RecursiveFirstOrDefaultLinq(childrenSelector, condition)).FirstOrDefault(result => result != null);
}

Test:

private void ButtonTest_OnClick(object sender, RoutedEventArgs e)
{
    VariationSet varSetResult;
    Stopwatch watch = new Stopwatch();

    varSetResult = null;
    watch.Start();
    for(int n = 0; n < 10000000; n++)
    {
        varSetResult = Model.VariationRef.VariationSet.RecursiveFirstOrDefault((varSet) => varSet.VariationSets,
            (varSet) => varSet.Name.Contains("Laure"));
    }
    watch.Stop();
    Console.WriteLine(watch.ElapsedMilliseconds.ToString() + " milliseconds");
    Console.WriteLine(varSetResult.Name);

    watch.Reset();

    varSetResult = null;
    watch.Start();
    for(int n = 0; n < 10000000; n++)
    {
        varSetResult = Model.VariationRef.VariationSet.RecursiveFirstOrDefaultLinq((varSet) => varSet.VariationSets,
            (varSet) => varSet.Name.Contains("Laure"));
    }
    watch.Stop();
    Console.WriteLine(watch.ElapsedMilliseconds.ToString() + " milliseconds");
    Console.WriteLine(varSetResult.Name + " LINQ");

}

I need to go today ... I hope to answer the tests correctly: x86, Release on a 12-core computer, Windows 7, Framework.Net 4.5,

My conclusion:

~ 3 non linq. LINQ, , , , ( - ). LINQ , . :

  • LINQ: ( )
  • Non Linq: , , .
+4
1

, LINQ LINQ:

  • . , .. LINQ Select FirstOrDefault, , LINQ.
  • Func<>, , , , . , , , .
  • LINQ , . .

?

. , LINQ 50% , , , , 400 . , , , , .

+3

All Articles