I am having trouble understanding the difference between covariance and contravariance.
I am having trouble understanding the difference between covariance and contravariance.
Share
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
The question is “what is the difference between covariance and contravariance?”
Covariance and contravariance are properties of a mapping function that associates one member of a set with another. More specifically, a mapping can be covariant or contravariant with respect to a relation on that set.
Consider the following two subsets of the set of all C# types. First:
And second, this clearly related set:
There is a mapping operation from the first set to the second set. That is, for each T in the first set, the corresponding type in the second set is
IEnumerable<T>. Or, in short form, the mapping isT → IE<T>. Notice that this is a “thin arrow”.With me so far?
Now let’s consider a relation. There is an assignment compatibility relationship between pairs of types in the first set. A value of type
Tigercan be assigned to a variable of typeAnimal, so these types are said to be “assignment compatible”. Let’s write “a value of typeXcan be assigned to a variable of typeY” in a shorter form:X ⇒ Y. Notice that this is a “fat arrow”.So in our first subset, here are all the assignment compatibility relationships:
In C# 4, which supports covariant assignment compatibility of certain interfaces, there is an assignment compatibility relationship between pairs of types in the second set:
Notice that the mapping
T → IE<T>preserves the existence and direction of assignment compatibility. That is, ifX ⇒ Y, then it is also true thatIE<X> ⇒ IE<Y>.If we have two things on either side of a fat arrow, then we can replace both sides with something on the right hand side of a corresponding thin arrow.
A mapping which has this property with respect to a particular relation is called a “covariant mapping”. This should make sense: a sequence of Tigers can be used where a sequence of Animals is needed, but the opposite is not true. A sequence of animals cannot necessarily be used where a sequence of Tigers is needed.
That’s covariance. Now consider this subset of the set of all types:
now we have the mapping from the first set to the third set
T → IC<T>.In C# 4:
That is, the mapping
T → IC<T>has preserved the existence but reversed the direction of assignment compatibility. That is, ifX ⇒ Y, thenIC<X> ⇐ IC<Y>.A mapping which preserves but reverses a relation is called a contravariant mapping.
Again, this should be clearly correct. A device which can compare two Animals can also compare two Tigers, but a device which can compare two Tigers cannot necessarily compare any two Animals.
So that’s the difference between covariance and contravariance in C# 4. Covariance preserves the direction of assignability. Contravariance reverses it.