Covariance, contravariance and invariance describe how the existing type inheritance hierarchy changes when subjected to some transformation (such as usage within generics). If the transformation keeps the ordering of the original hierarchy, it is "covariant". If it reverses it, it is "contravariant". If it breaks it, it is "invariant".
About Type Ordering
Let's say that a class P (parent) is inherited by a class C (child).
We can denote this fact as: P > C.
Informally, P is "larger" than C since it "contains" all the possible instances of C, but can also contain some other instances that are not C. Child is always parent but not necessarily the other way around.
Variance in Generics
Let's say that there is a generic type G that has a single generic parameter T, denoted by: G{T}.
- If G{P} > G{C}, then T is co-variant (it preserves the original inheritance ordering).
- If G{P} < G{C}, then T is contra-variant (it reverses the original inheritance ordering).
- If G{P} and G{C} are type-unrelated, then T is invariant (it "breaks" the inheritance).
So the variance is the property of transformation (in this case: generic parameter T of G), not the original type hierarchy (P and C).
C# Examples
The generic parameter T of IEnumerable<out T>
is covariant (as denoted by "out" keyword), meaning you can "forget" that the collection contains Cs and just treat it as if it contains Ps. For example:
IEnumerable<C> ec = ...;
IEnumerable<P> ep = ec;
The generic parameter T of Action<in T>
is contravariant (as denoted by "in" keyword), meaning that an action that accepts P can also accept C. For example:
Action<P> ap = ...;
Action<C> ac = ap;
The generic parameter T is contravariant and generic parameter TResult is covariant in Func<in T, out TResult>
. Each generic parameter is considered a different "transformation" with its own variance. This lets you write a code like this:
Func<P, C> fpc = ...;
Func<C, P> fcp = fpc;
And finally, the generic parameter T of IList<T>
is considered invariant, so IList<P>
and IList<C>
are considered unrelated types (there is no assignment compatibility in either direction).
Tag usage
- Do not use covariance for the measurement of the strength and direction of the linear relationship between two random variables (statistical context). Instead, use other related tags, for example, statistics.
Moreover, consider whether the question might be better suited to Cross Validated, the Stack Exchange site for statistics, machine learning and data analysis.