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
37
votes
5 answers

Why is Function[-A1,...,+B] not about allowing any supertypes as parameters?

I believe one can define covariance (at least, for objects) as 'the ability to use a value of a narrower (sub) type in place of a value of some wider (super) type', and that contravariance is the exact opposite of this. Apparently, Scala functions…
bjt38
  • 533
  • 4
  • 8
36
votes
7 answers

Make dictionary read only in C#

I have a Dictionary> and would like to expose the member as read only. I see that I can return it as a IReadOnlyDictionary>, but I can't figure out how to return it as an IReadOnlyDictionary
bpeikes
  • 3,495
  • 9
  • 42
  • 80
36
votes
6 answers

When is C++ covariance the best solution?

This question was asked here a few hours ago and made me realise that I have never actually used covariant return types in my own code. For those not sure what covariance is, it's allowing the return type of (typically) virtual functions to differ…
anon
35
votes
6 answers

Why can't I cast from a List to List?
I have a List of objects, which are of my type QuoteHeader and I want to pass this list as a list of objects to a method which is able to accept a List. My line of code reads... Tools.MyMethod((List)MyListOfQuoteHeaders); But I get…
Karl
  • 912
  • 2
  • 16
  • 28
34
votes
4 answers

What is the difference between covariance and contra-variance in programming languages?

Can anyone explain the concept of covariance and contravariance in programming language theory?
xdevel2000
  • 20,780
  • 41
  • 129
  • 196
34
votes
4 answers

Covariance and Overloading in Java

class A { boolean f(A a) { return true; } } class B extends A { boolean f(A a) { return false; } // override A.f(A) boolean f(B b) { return true; } // overload A.f } void f() { A a = new A(); A ab = new B(); B b = new B(); …
nabil
  • 904
  • 3
  • 12
  • 28
33
votes
5 answers

How to get around lack of covariance with IReadOnlyDictionary?

I'm trying to expose a read-only dictionary that holds objects with a read-only interface. Internally, the dictionary is write-able, and so are the objects within (see below example code). My problem is that IReadOnlyDictionary doesn't support…
Ocelot20
  • 10,510
  • 11
  • 55
  • 96
31
votes
2 answers

Why is parameter in contravariant position?

I'm trying to use a covariant type parameter inside a trait to construct a case-class like so: trait MyTrait[+T] { private case class MyClass(c: T) } compiler says: error: covariant type T occurs in contravariant position in type T of value c I…
lapislazuli
  • 506
  • 4
  • 6
30
votes
2 answers

Parameter type covariance in specializations

tl;dr What strategies exist to overcome parameter type invariance for specializations, in a language (PHP) without support for generics? Note: I wish I could say my understanding of type theory/safety/variance/etc., was more complete; I'm no CS…
Dan Lugg
  • 20,192
  • 19
  • 110
  • 174
29
votes
7 answers

c# covariant return types utilizing generics

Is the code below the only way to implement covariant return types? public abstract class BaseApplication { public T Employee{ get; set; } } public class Application : BaseApplication {} public class NewApplication :…
Brian
  • 1,027
  • 2
  • 11
  • 17
29
votes
1 answer

Why covariance does not work with generic method

Assume I have interface and class: public interface ITree {} public class Tree : ITree {} As IEnumerable is covariant, the code line below is compiled successfully: IEnumerable trees = new List(); But when I put it into generic…
cuongle
  • 74,024
  • 28
  • 151
  • 206
28
votes
3 answers