Подтвердить что ты не робот

Почему ICollection <T> не реализует ICollection?

IEnumerable<T> реализует IEnumerable.
Но ICollection<T> не реализует ICollection.

Каково было обоснование этого и/или было ли это просто надзором?

4b9b3361

Ответ 1

Как сказал Ник, ICollection почти бесполезен.

Эти интерфейсы похожи только на их имя, CopyTo и Count - единственные общие свойства. Add, Remove, Clear, Contains и IsReadOnly были добавлены, а IsSychronized и SyncRoot были удалены.

По существу, ICollection<T> является изменяемым, ICollection не является.

Krzysztof Cwalina имеет больше на этой теме

ICollection<T> выглядит как ICollection, но на самом деле это совсем другая абстракция. Мы обнаружили, что ICollection не очень полезен. В то же время у нас не было абстракции, которая представляла собой неиндексированную коллекцию чтения/записи. ICollection<T> является такой абстракцией, и вы можете сказать, что ICollection не имеет точного соответствующего партнера в родовом мире; IEnumerable<T> является самым близким.

Ответ 2

ICollection<T> и ICollection на самом деле очень разные интерфейсы, к которым, к сожалению, принадлежит имя и не более того.

Из http://blogs.msdn.com/b/kcwalina/archive/2005/09/23/collections.aspx

ICollection<T> выглядит как ICollection, но на самом деле это совсем другая абстракция. Мы обнаружили, что ICollection не очень полезен. В то же время у нас не было абстракции, которая представляла собой неиндексированную коллекцию чтения/записи. ICollection<T> - такая абстракция, и вы могли бы сказать, что ICollection не имеет точного соответствующего партнера в родовом мире; IEnumerable<T> является самым близким.

Ответ 3

Во-первых, 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 утвердительного ответа.

Ответ 4

Оба 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 при любых обстоятельствах и поэтому не может наследовать его.