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
14
votes
2 answers

ICollection not Covariant?

The purpose of this is to synchronize two collections, sender-side & receiver-side, containing a graph edge, so that when something happens (remove edge, add edge, etc) both sides are notified. To do so, (back-)references to the collections were…
Jeffrey Goines
  • 935
  • 1
  • 11
  • 30
14
votes
2 answers

covariant type T occurs in invariant position

I'm moving my first steps in Scala and I would like to make the following code works: trait Gene[+T] { val gene: Array[T] } The error that the compiler gives is: covariant type T occurs in invariant position in type => Array[T] of value gene I…
Vincenzo Maggio
  • 3,787
  • 26
  • 42
13
votes
4 answers

Covariance and Contravariance in C#

I will start by saying that I am Java developer learning to program in C#. As such I do comparisons of what I know with what I am learning. I have been playing with C# generics for a few hours now, and I have been able to reproduce the same things…
Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
13
votes
3 answers

Covariance/contravariance: how to make the following code compile

UPDATE: The following code only makes sense in C#4.0 (Visual Studio 2010) It seems like I am having some misunderstanding of covariance/contravariance thing. Can anybody tell me why the following code doesn't compile? public class TestOne { …
Trident D'Gao
  • 18,973
  • 19
  • 95
  • 159
13
votes
1 answer

DELPHI: Generics and polymorphism

This has been asked several different ways already - but I haven't found my answer yet. Can someone clarify a few things for me please. Using : Delphi XE2 I have quite a big BaseObject that I use for almost everything. Along with it I have a Generic…
Bimmer_R
  • 588
  • 9
  • 18
13
votes
4 answers

Why do C# out generic type parameters violate covariance?

I'm unclear as to why the following code snippet isn't covarient? public interface IResourceColl : IEnumerable where T : IResource { int Count { get; } T this[int index] { get; } bool TryGetValue( string SUID, out T obj );…
MerickOWA
  • 7,453
  • 1
  • 35
  • 56
13
votes
5 answers

Why does C#/CLR not support method override co/contra-variance?

There are quite a few questions & answers about hacking around the limitation of C# not allowing method return (and argument) types to be changed to compatible types on overrides, but why does this limitation exist, either in the C# compiler or in…
thecoop
  • 45,220
  • 19
  • 132
  • 189
13
votes
1 answer

How to combine 2different IQueryable/List/Collection with same base class? LINQ Union and Covariance issues

I am trying to combine (union or concat) two lists/collection into one. The two lists have a common base class. e.g. I've tried this: IQueryable contractItems = myRepository.RetrieveContractItems(); …
Raymond
  • 3,382
  • 5
  • 43
  • 67
13
votes
4 answers

C++ How do I pass a list of non-consts to a function wanting a list of consts

I have a function with a signature void Foo(list) and I want to pass it a list How do I do this? (plz note - the list isn't constant, only the member of the list)
vondip
  • 13,809
  • 27
  • 100
  • 156
13
votes
2 answers

Java automatic return type covariance with generic subclassing

I have two interfaces that look like this: interface Parent { T foo(); } interface Child extends Parent { } If I have a raw Parent object, calling foo() defaults to returning a Number since there is no…
Nick Lowery
  • 187
  • 1
  • 7
13
votes
5 answers

Override a Property with a Derived Type and Same Name C#

I'm trying to override a property in a base class with a different, but derived type with the same name. I think its possible by covarience or generics but am not sure how to do it? The following code gets the error: Error 1 'Sun.Cache': type must…
JaredBroad
  • 660
  • 1
  • 8
  • 17
13
votes
2 answers

could someone explain the connection between type covariance/contravariance and category theory?

I am just starting to read about category theory, and would very much appreciate it if someone could explain the connection between CS contravariance/covariance and category theory. What would some example categories be (i.e. what are their…
gatoatigrado
  • 16,580
  • 18
  • 81
  • 143
13
votes
3 answers

C# compiler fails to recognize a class is implementing an interface

The following code fails to compile (using VS2010) and I don't see why. The compiler should be able to infer that List is 'compatible' (sorry for lack of a better word) with IEnumerable, but somehow it doesn't. What am I missing…
Freek
  • 1,506
  • 1
  • 11
  • 25
13
votes
1 answer

Question about C# 4.0's generics covariance

Having defined this interface: public interface IInputBoxService { bool ShowDialog(); T Result { get; } } Why does the following code work: public class StringInputBoxService : IInputBoxService { …
devoured elysium
  • 101,373
  • 131
  • 340
  • 557
13
votes
3 answers

C++: How can I avoid "invalid covariant return type" in inherited classes without casting?

I have a quite complex class hierarchy in which the classes are cross-like depending on each other: There are two abstract classes A and C containing a method that returns an instance of C and A, respectively. In their inherited classes I want to…
Searles
  • 1,447
  • 1
  • 11
  • 26