Covariance & Contravariance
- Covariant if it preserves the ordering of types (≤), which orders types from more specific to more generic;
- Contravariant if it reverses this ordering;
- Bivariant if both of these apply (i.e., both
I<A>
≤I<B>
andI<B>
≤I<A>
at the same time); - Invariant or Nonvariant if neither of these applies.
In C# interfaces, in
represents contravariance, and out
represents covariance.
For example in C#, if Cat
is a subtype of Animal
, then:
IEnumerable<Cat>
is a subtype of IEnumerable<Animal>
. The subtyping is preserved because IEnumerable<T>
is covariant on T
.
Action<Animal>
is a subtype of Action<Cat>
. The subtyping is reversed because Action<T>
is contravariant on T
.
Neither IList<Cat>
nor IList<Animal>
is a subtype of the other, because IList<T>
is invariant on T
.