3

What difference between

FirstOrDefault(someField => someField.Name.Equals(settings.Text))

and

Where(someField => someField.Name.Equals(settings.Text)).FirstOrDefault() 

?

As far as I understand in both cases Linq will run till the first occurence that suits the condition.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Jviaches
  • 826
  • 3
  • 14
  • 30

2 Answers2

9

They result of both statements is the same. You can think of the first one as a shorter version of the second one.

The FirstOrDefault method has an overload taking in a second parameter, a Func<TSource, bool> which is the same predicate you are defining in your Where statement.

Jensen
  • 3,498
  • 2
  • 26
  • 43
  • @wudzik Really? I would guess properly optimized SQL would look the same. – Euphoric Dec 05 '13 at 07:39
  • In older version of entity framework the first option will not work, and the second will, and I don't know why. but I faced with it in some project. – Tony Dec 05 '13 at 07:43
6

If we are talking about Linq to Objects, then there is one notable difference. Second statement

Where(someField => someField.Name.Equals(settings.Text)).FirstOrDefault() 

Will create WhereEnumerableIterator internally, and then it will start enumeration and take first item:

// argument checks and collection optimizations removed
public static IEnumerable<TSource> Where<TSource>(
     this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
     // it enumerates source and returns items which match predicate
     return new WhereEnumerableIterator<TSource>(source, predicate);
}

public static TSource First<TSource>(this IEnumerable<TSource> source)
{
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        if (enumerator.MoveNext())        
            return enumerator.Current;        
    }

    throw Error.NoElements();
}

But first statement will just take first item from source which matches predicate without creating additional enumerator:

// argument checks removed
public static TSource First<TSource>(
    this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{    
    foreach (TSource local in source)
    {
        if (predicate(local))        
            return local;        
    }

    throw Error.NoMatch();
}

So, first one is better in terms of performance:

FirstOrDefault(someField => someField.Name.Equals(settings.Text))
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459