To get covariance you should have something like this:
public interface IAnimal {
}
public class Lion : IAnimal {}
public class Sheep : IAnimal {}
// note the "out" on the T type parameter
public interface ICage<out T> where T:IAnimal {
T SomeAnimal {get;}
}
public class Cage<T> : ICage<T> where T:IAnimal {
public T SomeAnimal { get; set; }
}
you can now do this:
// without covariance on ICage you can't assign a 'Cage<Sheep>' to 'ICage<IAnimal>'
ICage<IAnimal> sheeps = new Cage<Sheep>() {SomeAnimal=new Sheep()};
ICage<IAnimal> lions = new Cage<Lion>() {SomeAnimal=new Lion()};
or this (creating a heterogeneous list of Cage<IAnimals>
with both Cages of Sheeps and Cages of Lions), which is an equivalent but probably more useful example:
// without covariance on ICage it errors: cannot convert from 'Cage<Sheep>' to 'ICage<IAnimal>'
var zoo = new List<ICage<IAnimal>>{
new Cage<Sheep> {SomeAnimal=new Sheep()},
new Cage<Lion> {SomeAnimal=new Lion()},
};
if you try removing the out
from the declaration of ICage
you will see the difference.