Both ICollection
and ICollection<T>
contain at least one method that returns the collection type (GetEnumerator
) and another that takes it as an argument (CopyTo
).
ICollection<T>.GetEnumerator
is covariant with ICollection.GetEnumerator
, because T
is a more specific type than System.Object
. This part is OK. This is why IEnumerable<T>
is able to subclass (and thus be substitutable) for IEnumerable
.
But if we want ICollection<T>
to be substitutable for ICollection
, we also need ICollection<T>.CopyTo
to be contravariant with ICollection.CopyTo
, which it is not. The ICollection<T>.CopyTo
method cannot accept a parameter of a less-specific type than T
(the generics grammar constrains it to be T
or smaller). And if ICollection<T>.CopyTo
method is not contravariant in its argument, then that means the ICollection<T>
interface as a whole is not substitutable for ICollection
.
That might be a little hard to make sense of; it's more complicated because it deals with arrays. It's blindingly obvious in IList<T>
, where implementing both interfaces could potentially break the type safety that's supposed to be guaranteed by generics (by simply invoking the non-generic IList.Add
method). But that's actually just another way of saying that the IList<T>.Add
method is not contravariant in its arguments with IList.Add
- the generic method cannot accept the less-specific type System.Object
as an argument.
Long story short: ICollection<T>
simply can't be made substitutable for ICollection
under all circumstances, and therefore cannot inherit from it.