IEnumerable<T>
реализует IEnumerable
.
Но ICollection<T>
не реализует ICollection
.
Каково было обоснование этого и/или было ли это просто надзором?
IEnumerable<T>
реализует IEnumerable
.
Но ICollection<T>
не реализует ICollection
.
Каково было обоснование этого и/или было ли это просто надзором?
Как сказал Ник, ICollection
почти бесполезен.
Эти интерфейсы похожи только на их имя, CopyTo
и Count
- единственные общие свойства. Add
, Remove
, Clear
, Contains
и IsReadOnly
были добавлены, а IsSychronized
и SyncRoot
были удалены.
По существу, ICollection<T>
является изменяемым, ICollection
не является.
Krzysztof Cwalina имеет больше на этой теме
ICollection<T>
выглядит какICollection
, но на самом деле это совсем другая абстракция. Мы обнаружили, чтоICollection
не очень полезен. В то же время у нас не было абстракции, которая представляла собой неиндексированную коллекцию чтения/записи.ICollection<T>
является такой абстракцией, и вы можете сказать, чтоICollection
не имеет точного соответствующего партнера в родовом мире;IEnumerable<T>
является самым близким.
ICollection<T>
и ICollection
на самом деле очень разные интерфейсы, к которым, к сожалению, принадлежит имя и не более того.
Из http://blogs.msdn.com/b/kcwalina/archive/2005/09/23/collections.aspx
ICollection<T>
выглядит какICollection
, но на самом деле это совсем другая абстракция. Мы обнаружили, чтоICollection
не очень полезен. В то же время у нас не было абстракции, которая представляла собой неиндексированную коллекцию чтения/записи.ICollection<T>
- такая абстракция, и вы могли бы сказать, чтоICollection
не имеет точного соответствующего партнера в родовом мире;IEnumerable<T>
является самым близким.
Во-первых, IList<T>
выполняет не реализацию IList
, возможно, по тем же причинам. IList<T>
реализует: ICollection<T>, IEnumerable<T>, IEnumerable
Некоторые части ICollection просто не нужны, но изменение интерфейса после него в дикой природе в лучшем случае прерывается.
Посмотрите на ICollection:
public interface ICollection : IEnumerable
{
void CopyTo(Array array, int index);
int Count { get; }
bool IsSynchronized { get; }
object SyncRoot { get; }
}
Это просто не свойства, которые вам нужны в большинстве случаев, когда мне нужна коллекция, которую я никогда не нуждался в этом, и не хотел бы ее реализовывать. Похоже, это было рассуждение, но я должен попросить команду .Net утвердительного ответа.
Оба ICollection
и ICollection<T>
содержат по крайней мере один метод, который возвращает тип коллекции (GetEnumerator
), а другой - как аргумент (CopyTo
).
ICollection<T>.GetEnumerator
ковариантно с ICollection.GetEnumerator
, потому что T
является более конкретным типом, чем System.Object
. Эта часть в порядке. Вот почему IEnumerable<T>
может подкласса (и, следовательно, быть подставляемым) для IEnumerable
.
Но если мы хотим, чтобы ICollection<T>
была подставляемой для ICollection
, нам также нужно, чтобы ICollection<T>.CopyTo
была контравариантна с ICollection.CopyTo
, а это не так. Метод ICollection<T>.CopyTo
не может принимать параметр менее специфического типа, чем T
(грамматика дженериков ограничивает его T
или меньше). И если метод ICollection<T>.CopyTo
не является контравариантным в своем аргументе, то это означает, что интерфейс ICollection<T>
в целом не подлежит замене для ICollection
.
Это может быть немного трудно понять; это сложнее, потому что речь идет о массивах. Это ослепительно очевидно в IList<T>
, где реализация обоих интерфейсов может потенциально нарушить безопасность типа, которая должна быть гарантирована генериками (путем простого вызова метода non-generic IList.Add
). Но это просто еще один способ сказать, что метод IList<T>.Add
не является контравариантным в своих аргументах с IList.Add
- общий метод не может принять менее специфический тип System.Object
в качестве аргумента.
Короче говоря: ICollection<T>
просто не может быть заменен на ICollection
при любых обстоятельствах и поэтому не может наследовать его.