Co- and Contra-variance
Within the type system of a programming language, an operator from types to types is covariant if it preserves the ordering, ≤, of types, which orders types from more specific ones to more generic ones; it is contra variant if it reverses this ordering. If neither of these applies, the operator is invariant.
This distinction is important in considering argument and return types of methods in class hierarchies. In object-oriented languages such as C++, if class B is a subtype of class A, then all member functions of B must return the same or narrower set of types as A; the return type is said to be covariant. On the other hand, the member functions of B must take the same or broader set of arguments compared with the member functions of A; the argument type is said to be contra variant.
Let’s take the following codes as an example.
string objs = new string;
static void Process(object objs)
objs = new ArgumentException();
You can code this in C# and compile it successfully because array in .net is covariance. But apparently, it’s not safe.
But if you do this:
List<string> strList = new List
IEnumerable<object> test3 = strList;
You will get a compile error, because until now C# generics are invariance. In C# 4.0, it provides us a safe co- and contra-variance.public interface IReader
Through the out keyword, you can allow the type argument T only to be output by the methods declared on the interface.
Contra variance is also supported through the in keyword. When this is used the type argument can only be used for arguments.
public interface IWriter
Section II 9.5 in the CLI specification covers this and the only difference from C# 4.0 is that + is used to denote covariance and - is used to denote contra variance.
Variant type parameters can only be declared on interfaces and delegate types, due to a restriction in the CLR. Variance only applies when there is a reference conversion between the type arguments. For instance, an IEnumerable<object>