My problem is that I have a method that can take a collection as parameter that,
Has a Count property
Has an integer indexer (get-only)
And I don't know what type should this parameter be. I would choose IList<T> before .NET 4.5 since there is no other indexable collection interface for this and arrays implement it, which is a big plus.
But .NET 4.5 introduces the new IReadOnlyList<T> interface and I want my method to support that, too. How can I write this method to support both IList<T> and IReadOnlyList<T> without violating the basic principles like DRY?
Can I convert IList<T> to IReadOnlyList<T> somehow in an overload?
What is the way to go here?
Edit: Daniel's answer gave me some pretty ideas, I guess I'll go with this:
public void Do<T>(IList<T> collection)
{
DoInternal(collection, collection.Count, i => collection[i]);
}
public void Do<T>(IReadOnlyList<T> collection)
{
DoInternal(collection, collection.Count, i => collection[i]);
}
private void DoInternal<T>(IEnumerable<T> collection,
int count, Func<int, T> indexer)
{
// Stuff
}
Or I could just accept a ReadOnlyList<T> and provide an helper like this:
public static class CollectionEx
{
public static IReadOnlyList<T> AsReadOnly<T>(this IList<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
return new ReadOnlyWrapper<T>(collection);
}
private sealed class ReadOnlyWrapper<T> : IReadOnlyList<T>
{
private readonly IList<T> _Source;
public int Count { get { return _Source.Count; } }
public T this[int index] { get { return _Source[index]; } }
public ReadOnlyWrapper(IList<T> source) { _Source = source; }
public IEnumerator<T> GetEnumerator() { return _Source.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
}
Then I could call Do(array.AsReadOnly())