C# 3.0 – Variance Explained
The problem:
Why can’t I create a List of type Dog and assign it to a List of type Animal?
IList<Animal> animals = new List<Dog>(); // no good
Theory:
There are 3 terms relating to variance:
Covariance – allows more specific types to be assigned to more general types. (i.e. sub-types (classes, interfaces) can be assigned to any types (classes, interfaces) that they inherit from).
C# Example: Method Return types are Covariant. We can return a sub-type of the method’s declaring return type.
IAnimal GetAnimal(string animalName) {...};
GetAnimal("dog") {return new Dog();} // the dog is more specific and returned as the general type IAnimal
GetAnimal("cat") {return new Cat();} // the cat is more specific and returned as the general type IAnimal
Contravariance – allows general types to accept more specific types – i.e. The reverse of covariance.
C# Example: Method parameters are Contravariant. We can call a method with a parameter that is a sub-type of the parameters declaring type.
IAnimal GetAnimal(IAnimal animal) {...};
GetAnimal(new Dog()); // the method takes a general type IAnimal but is called with the more specific type Dog
GetAnimal(new Cat()); // the method takes a general type IAnimal but is called with the more specific type Dog
Invariance – occurs when neither of these conditions are met.
C# Example: In C# 3.0 Generics are invariant. C# 4.0 allows the variance of generics to be defined (with restrictions).
IList<Animal> animals = new IList<Animal>();
animals.Add(new Dog());
animals.Add(new Cat());
IList<Animal> animals = new List<Dog>();
animals.Add(new Dog());
animals.Add(new Cat()); // no dice. You can’t assign a cat to a list of dogs.
Tags: Contravariance, Contravariant, Covariance, Covariant, Generics, Invariance, Invariant, Subclass, Variance
There is a nice FAQ up on MSDN about contravariance and covariance for c# 4.0 here – http://blogs.msdn.com/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
C# 4.0 is out now with all the new contravariance and covariance goodies!