Как сказал Ник, ICollection
практически бесполезен.
Эти интерфейсы похожи только названием, CopyTo
и Count
- единственные общие свойства. Add
, Remove
, Clear
, Contains
и IsReadOnly
были добавлены, а IsSychronized
и SyncRoot
были удалены.
По сути, ICollection
- мутабельный, ICollection
- нет.
Krzysztof Cwalina имеет больше информации на эту тему
ICollection
кажется похожей наICollection
, но на самом деле это совсем другая абстракция. Мы обнаружили, чтоICollection
не очень полезен. В то же время у нас не было абстракции, которая представляла бы неиндексированную коллекцию с возможностью чтения/записи.ICollection
является такой абстракцией, и можно сказать, чтоICollection
не имеет точного аналога в общем мире;IEnumerable
является наиболее близким.
Во-первых, IList
не реализует IList
, вероятно, для по тем же причинам. IList
реализует: ICollection
Некоторые части ICollection просто не нужны, но изменение интерфейса после того, как он вышел в дикой природе, ломка в лучшем случае.
Посмотрите на ICollection:
public interface ICollection : IEnumerable
{
void CopyTo(Array array, int index);
int Count { get; }
bool IsSynchronized { get; }
object SyncRoot { get; }
}
Это просто не свойства, которые вам нужны в большинстве случаев, когда я хочу коллекцию, я никогда не нуждался в этом и не хотел бы его реализовывать. Я полагаю, что это устарело, но вам придется попросить утвердительный ответ у команды .Net.
И ICollection
, и ICollection
содержат по крайней мере один метод, возвращающий тип коллекции (GetEnumerator
), и другой, принимающий его в качестве аргумента (CopyTo
).
ICollection
ковариантен с ICollection.GetEnumerator
, потому что T
- более конкретный тип, чем System.Object
. Эта часть в порядке. Именно поэтому IEnumerable
может быть подклассом (и таким образом быть заменяемым) для IEnumerable
.
Но если мы хотим, чтобы ICollection
была заменяемой для ICollection
, нам также нужно, чтобы ICollection
была контравариантна ICollection.CopyTo
, а это не так. Метод ICollection
не может принимать параметр типа меньше, чем T
(грамматика generics ограничивает его значением T
или меньше). И если метод ICollection
не является контравариантным по своему аргументу, то это означает, что интерфейс ICollection
в целом не заменяем на ICollection
.
Это может быть немного трудно понять; это сложнее, потому что имеет дело с массивами. Это ослепительно очевидно в IList
, где реализация обоих интерфейсов потенциально может нарушить безопасность типов, которая должна быть гарантирована дженериками (просто вызывая недженерический метод IList.Add
). Но на самом деле это просто другой способ сказать, что метод IList
не является контравариантным в своих аргументах с IList.Add
- родовой метод не может принять в качестве аргумента менее специфичный тип System.Object
.
Короче говоря: ICollection
просто не может быть заменен на ICollection
при любых обстоятельствах, и поэтому не может наследоваться от него.