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
10
votes
3 answers

Interfaces inheritance in C#

I'm trying to overrun quite big (for me) problem that I came across while writing my application. Look at this, please (I will try to shorten the code for simplicity): I have root interface called IRepository. Next, IBookRepository :…
skrzeczowas
  • 125
  • 1
  • 1
  • 6
10
votes
3 answers

Why is C# 4.0's covariance/contravariance limited to parameterized interface and delegate types?

Is this a limitation of the CLR or are there compatibility concerns with existing code? Is this related to the messed up variance of delegate combining in C# 4.0? Edit: Would it be possible to have a language using co-/contravariance without that…
soc
  • 27,983
  • 20
  • 111
  • 215
10
votes
2 answers

Is it possible to implement the "virtual constructor" pattern in C# without casts?

I'm writing a program that writes C# that eventually gets compiled into an application. I would like each of the generated types to provide a "deep clone" function which copies the entire tree of data. That is, I want someone to be able to do: var x…
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
10
votes
4 answers

Generic type inference with multiply-implemented covariant interfaces, how to work around it?

Consider this silly program that does nothing: interface I { } class A1 : I { } class A2 : A1, I { } class B1 { } class B2 : B1, I { } class C1 : I { } class C2 : C1, I { } static class Program { static void f(I
user743382
10
votes
3 answers

How is generic function implemented in java?

As per my understanding the following generic function in java: public static T f(T x) { Integer[] arr = new Integer[4]; T ret = (T) arr[2]; return ret; } is compiled to the following form (as it is unbounded): public static Object…
user236215
  • 7,278
  • 23
  • 59
  • 87
10
votes
3 answers

Variance rules in C#

The Exact rules for variance validity are a bit vague and not specific. I'm going to list the rules for what makes a type valid-covariantly, and attach some queries and personal annotations to each of those rules. A type is valid covariantly if it…
Garrett Biermann
  • 537
  • 1
  • 4
  • 12
10
votes
8 answers

Why is void not covariant in Java?

If I have this interface: public interface Foo { void bar(); } Why can't I implement it like this? public class FooImpl implements Foo { @Override public Object bar() { return new Object(); } } It seems like void should be…
MattWallace
  • 1,015
  • 6
  • 12
9
votes
3 answers

Why can't I cast a dictionary of one value type to dictionary of another value type when the value types can be cast from one another?

Possible Duplicate: In C#, why can't a List object be stored in a List variable Why doesn't the below work? List castMe = new List(); IEnumerable getFromCast = (IEnumerable)castMe; //…
user420667
  • 6,552
  • 15
  • 51
  • 83
9
votes
3 answers

generics covariance and explicit casting

If I try and do: IDictionary> dict = new Dictionary>(); I get the error: error CS0266: Cannot implicitly convert type 'System.Collections.Generic.Dictionary>' to …
GazTheDestroyer
  • 20,722
  • 9
  • 70
  • 103
9
votes
3 answers

How to deal with covariance when returning collection in c#?

I have a problem with returning collection and covariance and I was wondering if anyone has a better solution. The scenario is this: I have 2 version of implementation and I would like to keep the version implementation completely separate (even…
Khronos
  • 121
  • 2
9
votes
2 answers

Autofac: Resolving variant types with both in and out type arguments

This question is a follow up of my previous question: Autofac: Hiding multiple contravariant implementations behind one composite. I'm trying to find the boundries of what we can do with Autofac's covariance and contravariance support. I noticed…
Steven
  • 166,672
  • 24
  • 332
  • 435
9
votes
4 answers

C# Covariance and Contravariance when implementing interfaces

I've recently decided to refresh my memory regarding C# basics, so this might be trivial, but i've bumped into the following issue: StringCollection was used in .NET v1.0 in order to create a strongly typed collection for strings as opposed to an…
Mikey S.
  • 3,301
  • 6
  • 36
  • 55
9
votes
6 answers

overriding virtual function return type differs and is not covariant

Ah, SO came back just in time. I am getting a strange error: 'B::blah': overriding virtual function return type differs and is not covariant from 'A::blah' Here is the code causing the problem: class A { public: class Inner { }; virtual…
Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
9
votes
1 answer

Covariance/Contravariance with a linq expression

I have a function called "CreateCriteriaExpression" that takes a json string and creates a linq expression from it. This method is called by another called "GetByCriteria", which calls the "CreateCriteriaExpression" method and then executes that…
Amanda Kitson
  • 5,477
  • 12
  • 49
  • 73
9
votes
4 answers

c#4.0: int a real subtype of object? covariance, ienumerable and value types

I wonder why IEnumerable can't be assigned to a IEnumerable. After all IEnumerable is one of the few interfaces that supports covariance... The subtype relation and covariance stuff works with reference types int seems to be a proper…
Sebastian Gregor
  • 345
  • 2
  • 11