IList<T>
is never a subtype of a different IList<T1>
. IList
is invariant in its type parameter.
class Animal { /* ... */ }
class Dog : Animal { /* ... */ }
IList<Dog> dogs = new List<Dog>();
IList<Animal> animals = dogs; // type error
There is no subtype relationship for lists because you can put values into a list and take values out of a list.
If IList
was covariant, you'd be able to add items of the wrong subtype to a given list.
IList<Animal> animals = new List<Dog>(); // supposing this were allowed...
animals.Add(new Giraffe()); // ... then this would also be allowed, which is bad!
If IList
was contravariant, you'd be able to extract values of the wrong subtype from a given list.
IList<Dog> dogs = new List<Animal> { new Dog(), new Giraffe() }; // if this were allowed...
Dog dog = dogs[1]; // ... then this would be allowed, which is bad!
Invariant type parameters are declared by omitting both the in
and out
keywords.
interface IList<T> { /* ... */ }