Questions tagged [covariance]

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 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, .
    Moreover, consider whether the question might be better suited to Cross Validated, the Stack Exchange site for statistics, machine learning and data analysis.
1905 questions
18
votes
1 answer

Functions are contravariant in their argument types and co-variant in their return types

I have read this and this answers before posting this question, but I am still a bit unclear in my understanding of this topic as explained below: I understand what covariant and contravariant independently mean. If I have classes as below: class…
rgamber
  • 5,749
  • 10
  • 55
  • 99
18
votes
1 answer

Cast Generic to Generic

I have a base WPF UserControl that handles some common functionality for derived UserControls. In the code-behind of any derived UserControl I call an event private void SomeClick(object sender, RoutedEventArgs e) { HandleClick(sender); …
juergen d
  • 201,996
  • 37
  • 293
  • 362
18
votes
1 answer

Covariance broken in C# arrays?

Consider following generic interface ITest with a covariant type parameter T, the generic class Test implementing the interface, and a class A and with a subclass B: interface ITest {     T prop{ get;} } class Test : ITest {     …
JE42
  • 4,881
  • 6
  • 41
  • 51
18
votes
4 answers

Why is Action> covariant?

This is something I'm having a hard time wrapping my head around. I understand that Action is contravariant and is probably declared as such. internal delegate void Action(T t); However, I don't understand why an Action> is…
Tejas Sharma
  • 3,420
  • 22
  • 35
17
votes
4 answers

What are the benefits of covariance and contravariance?

C# 4.0 is going to support covariance and contravariance. But I don't clearly understand the benefits of this new feature. Can you explain me (clearly) why we need it?
Delta76
  • 13,931
  • 30
  • 95
  • 128
17
votes
2 answers

In C# 4.0 why can't an out parameter in a method be covariant?

Given this magical interface: public interface IHat { TRabbit Take(); } And this class hierarchy: public class Rabbit { } public class WhiteRabbit : Rabbit { } I can now compile this: IHat hat1 = null; IHat
Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
17
votes
5 answers

Why do we need new keywords for Covariance and Contravariance in C#?

Can someone explain why there is the need to add an out or in parameter to indicate that a generic type is Co or Contra variant in C# 4.0? I've been trying to understand why this is important and why the compiler can't just figure it…
JoshBerke
  • 66,142
  • 25
  • 126
  • 164
17
votes
5 answers

Understanding Covariance and Contravariance in C# 4.0

I watched a video about it on Channel 9 but I didn't really understand it much. Can someone please give me a simple example about these that's easy to understand? After that maybe how it would be used in practice?
Joan Venge
  • 315,713
  • 212
  • 479
  • 689
16
votes
2 answers

Generic Covariance and contravariance

Consider the code snippet. IList obj=new List(); IEnumerable obj1 = obj; But if i write ICollection obj2 = obj; it throws me a compile time error. Cannot implicitly convert type…
Ashley John
  • 2,379
  • 2
  • 21
  • 36
16
votes
2 answers

How are co- and contra-variance used in designing business applications?

I know about using co- and contravariance in the standard library (e.g. collections and trait Function) I wonder how co- and contravariance are used in design of "real world" business applications.
Michael
  • 10,185
  • 12
  • 59
  • 110
16
votes
3 answers

Generic Variance in C# 4.0

Generic Variance in C# 4.0 has been implemented in such a way that it's possible to write the following without an exception (which is what would happen in C# 3.0): List intList = new List(); List objectList = intList; [Example…
Daniel May
  • 8,156
  • 1
  • 33
  • 43
16
votes
2 answers

Why can't the compiler tell the better conversion target in this overload resolution case? (covariance)

Understanding the C# Language Specification on overload resolution is clearly hard, and now I am wondering why this simple case fails: void Method(Func f) { } void Method(Func f) { } void Call() { Method(() => { throw new…
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
15
votes
3 answers

C# covariance structure understanding?

Assuming class A { } class B : A { } covariance is not supported for generic class. Meaning - we cant do something like this : MyConverter x1= new MyConverter(); MyConverter x2= x1; Thats fine and understood. From my…
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
15
votes
3 answers

Casting List - covariance/contravariance problem

Given the following types: public interface IMyClass { } public class MyClass : IMyClass { } I wonder how can I convert a List to a List? I am not completely clear on the covariance/contravariance topics, but I understand that I…
user256890
  • 3,396
  • 5
  • 28
  • 45
15
votes
4 answers

Question about C# covariance

In the code below: interface I1 { } class CI1: I1 { } List listOfCI1 = new List(); IEnumerable enumerableOfI1 = listOfCI1; //this works IList listofI1 = listOfCI1; //this does not I am able to assign my "listOfCI1" to an…
Raj Rao
  • 8,872
  • 12
  • 69
  • 83