2

Can anyone please tell me the difference between the following two lambda expressions:

    1. TabView mytab = TabCollection.Where(s => s.TabHeader == h).FirstOrDefault();

    2. TabView mytab = TabCollection.FirstOrDefault(s => s.TabHeader == h);

TabCollection is an ObservableCollection of type TabView.

4
  • 2
    I don't see any difference here. Commented Jul 15, 2013 at 21:54
  • 1
    Order of LINQ extension methods does not affect performance? Commented Jul 15, 2013 at 21:57
  • Less code + same results = Better Code. Use the second approach. type less. delay carpal tunnel. Commented Jul 15, 2013 at 21:57
  • When you separate both methods from each other you have more options. You can use the Where query lazily, so on each iteration or method call it could yield a different result. You could also chain other linq methods if desired(e.g. OrderBy or Take(n)) whereas the FirstOrDefault "ends" the query. However, the second approach is a little bit more effficient and - more important - more readable since it's more direct. Commented Jul 15, 2013 at 22:02

2 Answers 2

5

The two statements will provide the same results.

The difference is in how the result is achieved. The second is slightly more efficient, as it does not need to generate an iterator for the Where method, and then get it's enumerator, and can instead directly enumerate the collection until a match is found.

Sign up to request clarification or add additional context in comments.

8 Comments

the difference is incredibly slight
@LukeMcGregor There is an extra iterator allocated for handling the Where enumeration - it's minor, but in a tight loop or performant code, avoiding allocations can be important. It'd be tough to measure in anything except a tight loop, though, since any gain would likely be reduced GC pressure more than saved CPU cycles.
@ReedCopsey - Good point about GC pressure :) Space complexity is often overlooked.
@TravisJ That is completely untrue. The Where() method returns an iterator, not a fully populated collection. When FirstOrDefault starts enumerating the IEnumerable<T> returned from Where, it enumerates it in a deferred, streaming manner. Both versions will still short circuit and stop checking once a match is found.
@TravisJ Yes - the first yield returned which exists (from first or default) will "stop" the Where iterator from continuing. Where does not need to check every item - it will only check items as FirstOrDefault enumerates them, which means it'll only check until a match is found and then stop.
|
3
TabCollection.Where(s => s.TabHeader == h).FirstOrDefault()

This creates WhereIterator and returns it. Then you starting iteration and return first element of it. That looks like

var iterator = new WhereEnumerableIterator<TSource>(TabCollection, predicate);

using (IEnumerator<TSource> enumerator = iterator.GetEnumerator())
{
   if (enumerator.MoveNext())
       return enumerator.Current;
}

return default(TSource);

Second one does not create iterator - it simply enumerates over source:

TabCollection.FirstOrDefault(s => s.TabHeader == h);

Same as

foreach (TSource local in TabCollection)
{
    if (predicate(local))        
        return local;        
}

return default(TSource);

So, second option is slightly more efficient.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.