9

I know this may sound duplicate question (like this or this ) but I wanted some clarity regarding the number iterations that will take place in this query.

My assumptions are as follows:

lets say I have collection of 1000 items.

  1. In Where() query, it iterates through each and every item and add it to IEnumerable. i.e. it will need O(n) always.

    foreach (var item in myList)
    {
        if(//<condition>)
        {
            //add it to list/enumerable
        }
        //continue through entire list
    }
    
  2. In FirstOrDefault(<condition>) query,it starts iterating through the collection and breaks the loop as soon as it gets the item matching the <condition> and returns single element or only if no item is matching <condition> then it will iterate through entire list.

so complexity can be from O(1) to O(n)

foreach (var item in myList)
{
    if(//<condition>)
    {
        //return item
        break;
    }
}

if this is correct then it will always be better to use FirstORDefault for a single item return.?

Community
  • 1
  • 1
deathrace
  • 908
  • 4
  • 22
  • 48
  • 3
    Big-O is expressed as the worst case scenario. `FirstOrDefault()` will be 0(n). – Jeroen Vannevel Nov 18 '13 at 15:39
  • 1
    For a single item return, you should use `FirstOrDefault` (or similar methods, e.g. `Single`), not `Where`, because that's what it best expresses. Whether it's faster than some other implementation is another question. – Tim S. Nov 18 '13 at 15:43

3 Answers3

15

Where is actually deferred - i.e. it does not have any cost until the enumeration happens.

Where looks kind of like this, and returns a new IEnumerable<T>.

foreach (var item in enumerable)
{
    if (condition)
    {
        yield return item;
    }
}

FirstOrDefault returns T.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
2

FirstOrDefault will stop checking (i.e. break) when/if it finds anything.

edit: However, as Daniel pointed out, Where is deferred, so you can also stop iterating yourself and it will have the same performance as FirstOrDefault (although then you might as well just use FirstOrDefault)

David S.
  • 5,965
  • 2
  • 40
  • 77
  • The point of the question is the OP thinks that `Where()` will fully enumerate the list before passed on to `FirstOrDefault`. Which means his assumption is incorrect, not correct. – Scott Chamberlain Nov 18 '13 at 15:40
2

FirstOrDefault enumerates the query while Where just returns a new enumerator. Below statements give the same results:

var result = coll.FirstOrDefault(predicate);
var result = coll.Where(predicate).FirstOrDefault();
tukaef
  • 9,074
  • 4
  • 29
  • 45