Does the IEnumerable listing in IList <TResult> enumerate a sequence and why would that be preferred?

In some decompiled source from dotPeek I found this interesting snippet in the body FirstOrDefault()

, defined after a quick check of the validation:

  IList<TSource> list = source as IList<TSource>;
  if (list != null)
      if (list.Count > 0)
          return list[0];
      using (IEnumerator<TSource> enumerator = source.GetEnumerator())
          if (enumerator.MoveNext())
              return enumerator.Current;


I find two curiosities in this.

First, would it be a source listing? It seems obvious that it would give that the property is .Count

defined for the IList, but what if the main sequence itself is lazy?

Second, if it lists the source, why would it be the chosen implementation? Doesn't it make sense to just use the code that follows if()



source to share

3 answers

You are perfectly correct that in theory a "lazy" sequence could implement IList<T>

, causing the property property to Count

unnecessarily enumerate the entire sequence, only for the generated elements to be discarded. In this case, the "optimization" chosen by FirstOrDefault will actually make things worse.

But in practice, it is usually assumed that only sequences that are collections that can provide fast access to items by index will implement IList<T>

. This is why, for example, it LinkedList<T>

does not implement this interface, even though it can provide all the functionality it needs.

However, this FirstOrDefault optimization is not really a big performance win for lists. At best, this prevents the enumerator object from being heaped. Not doing this optimization would not be the end of the world.



No, he doesn't list anything. It just checks if the object instance implements in source


and uses that interface.

The point of this interface is most likely optimized because accessing the element directly is better than using a counter.

And if you want to know more about how LINQ is implemented, check out Jon Skeet EduLinq .



First, would it be listing the source?

No, it will not. If this underlying collection is IList<T>

, it means that it always retains an updated property Count

that reflects the size of the collections, which is an operation O(1)

. There is no need to list. I have not come across a lazy collection that implements the above interface, as that would violate the users' assumption that a property Count

is a non-enumeration operation.

Second, if it lists the source , why would it be the chosen implementation?

It doesn't matter since no enumeration is performed, just simple.



All Articles