Using Linq to get the last N elements of a collection?

collection.Skip(Math.Max(0, collection.Count() - N));

This approach preserves item order without a dependency on any sorting, and has broad compatibility across several LINQ providers.

It is important to take care not to call Skip with a negative number. Some providers, such as the Entity Framework, will produce an ArgumentException when presented with a negative argument. The call to Math.Max avoids this neatly.

The class below has all of the essentials for extension methods, which are: a static class, a static method, and use of the this keyword.

public static class MiscExtensions
{
    // Ex: collection.TakeLast(5);
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int N)
    {
        return source.Skip(Math.Max(0, source.Count() - N));
    }
}

A brief note on performance:

Because the call to Count() can cause enumeration of certain data structures, this approach has the risk of causing two passes over the data. This isn’t really a problem with most enumerables; in fact, optimizations exist already for Lists, Arrays, and even EF queries to evaluate the Count() operation in O(1) time.

If, however, you must use a forward-only enumerable and would like to avoid making two passes, consider a one-pass algorithm like Lasse V. Karlsen or Mark Byers describe. Both of these approaches use a temporary buffer to hold items while enumerating, which are yielded once the end of the collection is found.

Leave a Comment