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

Why does linking lifetimes matter only with mutable references?

A few days ago, there was a question where someone had a problem with linked lifetimes of a mutable reference to a type which contained borrowed data itself. The problem was supplying a reference to the type with a borrow of the same lifetime as the…
jtepe
  • 3,242
  • 2
  • 24
  • 31
25
votes
2 answers

What does mean?

Resharper has suggested to change from interface IModelMapper { TTo Map(TFrom input); } into interface IModelMapper So I investigate a little and ended reading this article (found through a Wikipedia article)…
mhttk
  • 1,688
  • 1
  • 16
  • 29
25
votes
1 answer

C++ covariance in parameters

I wanted to know why C++ does not support co-variance in parameters like in example below or if there is a way to achieve it? class base { public: virtual base* func(base * ptr) { return new base(); } }; class derived : public base { public: …
user1578026
24
votes
2 answers

What are good reasons for choosing invariance in an API like Stream.reduce()?

Reviewing Java 8 Stream API design, I was surprised by the generic invariance on the Stream.reduce() arguments: U reduce(U identity, BiFunction accumulator, BinaryOperator combiner) A seemingly more…
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
24
votes
3 answers

java generics covariance

I am having trouble understanding the following article: http://www.ibm.com/developerworks/java/library/j-jtp01255.html Under, Generics are not covariant the author states, Because ln is a List, adding a Float to it seems perfectly legal. But if…
soocracy42
  • 251
  • 1
  • 2
  • 4
23
votes
5 answers

Why can't I assign a List to a List?

I defined the following class: public abstract class AbstractPackageCall { ... } I also define a subclass of this class: class PackageCall : AbstractPackageCall { ... } There are also several other subclases of…
anon
23
votes
1 answer

Why isn't `curve_fit` able to estimate the covariance of the parameter if the parameter fits exactly?

I don't understand curve_fit isn't able to estimate the covariance of the parameter, thus raising the OptimizeWarning below. The following MCVE explains my problem: MCVE python snippet from scipy.optimize import curve_fit func = lambda x, a: a *…
finefoot
  • 9,914
  • 7
  • 59
  • 102
22
votes
4 answers

Container covariance in C++

I know that C++ doesn't support covariance for containers elements, as in Java or C#. So the following code probably is undefined behavior: #include struct A {}; struct B : A {}; std::vector test; std::vector* foo =…
Daniel Gehriger
  • 7,339
  • 2
  • 34
  • 55
22
votes
3 answers

Why does C# (4.0) not allow co- and contravariance in generic class types?

What is the real reason for that limitation? Is it just work that had to be done? Is it conceptually hard? Is it impossible? Sure, one couldn't use the type parameters in fields, because they are allways read-write. But that can't be the answer, can…
Lars Corneliussen
  • 2,513
  • 2
  • 26
  • 36
22
votes
7 answers

Covariance with C# Generics

Given an interface IQuestion and an implementation of that interface AMQuestion, suppose the following example: List typed = new List(); IList nonTyped = typed; This example yields, as expected, a compile error…
Will Custode
  • 4,576
  • 3
  • 26
  • 51
22
votes
13 answers

Any simple way to explain why I cannot do List animals = new ArrayList()?

I know why one shouldn't do that. But is there way to explain to a layman why this is not possible. You can explain this to a layman easily : Animal animal = new Dog();. A dog is a kind of animal but a list of dogs is not a list of animals.
fastcodejava
  • 39,895
  • 28
  • 133
  • 186
22
votes
10 answers

numpy covariance matrix

Suppose I have two vectors of length 25, and I want to compute their covariance matrix. I try doing this with numpy.cov, but always end up with a 2x2 matrix. >>> import numpy as np >>> x=np.random.normal(size=25) >>> y=np.random.normal(size=25) >>>…
user13321
  • 323
  • 1
  • 3
  • 5
22
votes
1 answer

Why are contravariant parameter types in Java not allowed for overriding?

When overriding a method of a superclass, Java allows the return type to be covariant. Why are contravariant parameter types in contrast not allowed when overriding methods?
Will
  • 2,858
  • 6
  • 33
  • 50
21
votes
4 answers

Does I re-implement I if I is convertible to I by variance conversion?

interface ICloneable { T Clone(); } class Base : ICloneable { public Base Clone() { return new Base(); } } class Derived : Base, ICloneable { new public Derived Clone() { return new Derived(); } } Given these…
Michael Liu
  • 52,147
  • 13
  • 117
  • 150
21
votes
6 answers

Selectively disable subsumption in Scala? (correctly type List.contains)

List("a").contains(5) Because an Int can never be contained in a list of String, this should generate an error at compile-time, but it does not. It wastefully and silently tests every String contained in the list for equality to 5, which can never…
Shelby Moore III
  • 6,063
  • 1
  • 33
  • 36