What is the performance of the Last() extension method for List<T>?

Daren Thomas picture Daren Thomas · Sep 4, 2009 · Viewed 9.2k times · Source

I really like Last() and would use it all the time for List<T>s. But since it seems to be defined for IEnumerable<T>, I guess it enumerates the enumeration first - this should be O(n) as opposed to O(1) for directly indexing the last element of a List<T>.

Are the standard (Linq) extension methods aware of this?

The STL in C++ is aware of this by virtue of a whole "inheritance tree" for iterators and whatnot.

Answer

Martin Harris picture Martin Harris · Sep 4, 2009

I just used the Reference Source to look into the code for Last and it checks to see if it is a IList<T> first and performs the appropriate O(1) call:

public static TSource Last < TSource > (this IEnumerable < TSource > source) {
    if (source == null) throw Error.ArgumentNull("source");
    IList < TSource > list = source as IList < TSource > ;
    if (list != null) {
        int count = list.Count;
        if (count > 0) return list[count - 1];
    }
    else {
        using(IEnumerator < TSource > e = source.GetEnumerator()) {
            if (e.MoveNext()) {
                TSource result;
                do {
                    result = e.Current;
                } while ( e . MoveNext ());
                return result;
            }
        }
    }
    throw Error.NoElements();
}

So you have the slight overhead of a cast, but not the huge overhead of enumerating.