finiteList.Reverse().Take(count).Reverse();
or
finiteList.Skip(finiteList.Count() - count)
There is some overhead in doing this so a custom method would be better.
Update: A custom method
public static class EnumerableExtensions
{
public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int count)
{
if (source == null) throw new ArgumentNullException("source");
if (count < 0) throw new ArgumentOutOfRangeException("count");
if (count == 0) yield break;
var queue = new Queue<T>(count);
foreach (var t in source)
{
if (queue.Count == count) queue.Dequeue();
queue.Enqueue(t);
}
foreach (var t in queue)
yield return t;
}
}
Update: Changed the code a littlebit with ideas from dtb´s answer :-)
Comment to Bear: Look at this example:
var lastFive = Enumerable.Range(1, 10).TakeLast(5);
var lastFive2 = Enumerable.Range(1, 10).TakeLast2(5); //Bear´s way
Queue<int> q = (Queue<int>)lastFive2;
q.Dequeue();
//Is lastFive2 still last five? no...
You could potentially change the values of lastFive2
and therefore that approach can be unsafe or at least it´s not the functional way.
To Bear:
What I meant about safe is this:
var lastFive2 = Enumerable.Range(1, 10).TakeLast2(5); //Bear´s way
//some = Some method which you don't control - it could be from another assembly which represents a crazy plugin etc.
some(lastFive2);
//Now what?
In these cases you would have to make a copy to be sure. But in most cases your way would be fine - and a little bit more efficient than this so +1 :)
An idea is to use a queue which only have internal Enqueue etc.