/* http://goo.gl/53fWh * The first thing to understand is that it is a relation which is *variant. * If it preserves the direction of assignment, then it is covariant. */ public Covariance() { // A valid assignment operation Animal animal = new Giraffe(); // This line shows that IEnumerator<T> is covariant for type T IEnumerable<Animal> animals = new List<Giraffe>(); }
static void CombineVariances() { ReturnOneAnimal pickGiraffe = new ReturnOneAnimal(ReturnGiraffe); Giraffe giraffe = new Giraffe(); Rabbit rabbit = new Rabbit(); pickGiraffe(rabbit, giraffe); }
static void BrokenCovariance() { // An example showing how the covariance is broken wrt // Arrays in C# Animal[] animals = new Giraffe[10]; // Although the below code doesn't throw a compile time error, it will // fail at runtime because Rabbit != Giraffe animals[4] = new Rabbit(); }
static void MethodParamContravariance() { UseSpecificAnimals useSpecificAnimals = new UseSpecificAnimals(UseUnspecificAnimals); // While the delegate can accept the method which less derived params, // the method itself requires that correct objects are passed. Giraffe giraffe = new Giraffe(); Rabbit rabbit = new Rabbit(); useSpecificAnimals(giraffe, rabbit); }
public void ArrayCovariance() { // Arrays are always covariant since Animal[] animals = new Giraffe[10]; // and object[] strings = new String[5]; // but these can be misused, since arrays are broken (http://goo.gl/guLSO) // strings[0] = 12; // The above code compiles fine but breaks at runtime. }
static void ReturnTypeCovariance() { Giraffe giraffe = new Giraffe(); // This is an example of method group being covariant in their // return types. The delegate definition very clearly wants an // Animal from the method group but the definition of MakeGiraffe // returns a giraffe. // From the article at Eric Lippert's blog: http://goo.gl/bpDPPX // "The caller of func is never going to get anything that they’re // not capable of dealing with." AnimalMaker animalMaker = new AnimalMaker(giraffe.MakeGiraffe); }