Моя проблема в том, что у меня есть метод, который может взять коллекцию как параметр, который
- Имеет свойство
Count
- Имеет целочисленный индекс (get-only)
И я не знаю, какой тип должен иметь этот параметр. Я бы выбрал IList<T>
до .NET 4.5, так как для этого не было другого интерфейса для индексируемых коллекций, а массивы реализуют его, что является большим плюсом.
Но .NET 4.5 представляет новый интерфейс IReadOnlyList<T>
, и я хочу, чтобы мой метод тоже поддерживал это. Как я могу написать этот метод для поддержки как IList<T>
, так и IReadOnlyList<T>
без нарушения основных принципов, таких как DRY?
Можно ли преобразовать IList<T>
в IReadOnlyList<T>
как-то в перегрузке?
Каков путь сюда?
Изменить: ответ Даниэля дал мне некоторые идеи, я думаю, я могу пойти с этим:
public void Foo<T>(IList<T> collection)
{
this.Foo(collection, collection.Count, i => collection[i]);
}
public void Foo<T>(IReadOnlyList<T> collection)
{
this.Foo(collection, collection.Count, i => collection[i]);
}
private void Foo<T>(
IEnumerable<T> collection,
int count,
Func<int, T> indexer)
{
// Stuff
}
Изменить 2: Или я могу просто принять IReadOnlyList<T>
и предоставить вспомогательный помощник:
public static class CollectionEx
{
public static IReadOnlyList<T> AsReadOnly<T>(this IList<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
// I now check whether it already is IReadOnlyList<T>...
// ...like casperOne has suggested.
return collection as IReadOnlyList<T>
?? new ReadOnlyWrapper<T>(collection);
}
private sealed class ReadOnlyWrapper<T> : IReadOnlyList<T>
{
private readonly IList<T> source;
public int Count { get { return this.source.Count; } }
public T this[int index] { get { return this.source[index]; } }
public ReadOnlyWrapper(IList<T> source) { this.source = source; }
public IEnumerator<T> GetEnumerator() { return this.source.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
}
}
Тогда я мог бы назвать Do(array.AsReadOnly())
Изменить 3:. Факт fun: массивы реализуют как IList<T>
, так и IReadOnlyList<T>
.