I am trying to use an OrderedDictionary as an argument for the below extension function (by the way if you think collection.Reverse().Where(i => predicate(i)).Take(n) would be better, let me know!), but the generic OrderedDictionary implementation I use (based on this version) does not implement IList.
The collection only needs to provide access to its elements with an integer-based index (which OrderedDictionary does).
Is there another way to specify this requirement, without creating an overload?
/// <summary>
/// Return n elements, starting from the end of collection, that satisfy predicate.
/// </summary>
/// <param name="collection"></param>
/// <param name="predicate"></param>
/// <param name="n">Max number of elements to return</param>
/// <returns></returns>
public static IEnumerable<T> LastBefore<T>(this IList<T> collection, Func<T, bool> predicate, int n) {
if (collection == null)
{
throw new ArgumentNullException("collection");
}
for (int i = collection.Count - 1; i >= 0; i--)
{
if (n == 0) break;
if (predicate(collection[i]))
{
--n;
yield return collection[i];
}
}
}
I would suggest defining an IReadableList interface; were it not for the fact that a read-write indexer does not count as an implementation of a read-only indexer, such a thing could have been a parent of IList (IMHO, it should have been anyway). Existing IList implementations won’t implement IReadableList unless wrapped, alas, but having a read-only list interface would make the concept of covariance much more useful, since an IReadableList<Cat> could be used as an IReadableList<Animal>.
Incidentally, I tend to think that while IList<T> doesn’t inherit from the non-generic IList, perhaps it should. Any IList<T> could implement IList in type-safe fashion if the non-generic implementation is read-only. Even if one never actually read any objects from the non-generic IList, implementing it would make allow a routine which wants an IEnumerable<Animal> but is given an IList<Cat> [which of course implements IEnumerable<Cat>, and thus implicitly IEnumerable<Animal>] to get a Count of the collection without having to enumerate it.