Difference between Covariance & Contra-variance

前端 未结 5 1571
小鲜肉
小鲜肉 2020-11-22 10:20

I am having trouble understanding the difference between covariance and contravariance.

5条回答
  •  南旧
    南旧 (楼主)
    2020-11-22 10:46

    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:

    { Animal, 
      Tiger, 
      Fruit, 
      Banana }.
    

    And second, this clearly related set:

    { IEnumerable, 
      IEnumerable, 
      IEnumerable, 
      IEnumerable }
    

    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. Or, in short form, the mapping is T → IE. 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 Tiger can be assigned to a variable of type Animal, so these types are said to be "assignment compatible". Let's write "a value of type X can be assigned to a variable of type Y" 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:

    Tiger  ⇒ Tiger
    Tiger  ⇒ Animal
    Animal ⇒ Animal
    Banana ⇒ Banana
    Banana ⇒ Fruit
    Fruit  ⇒ Fruit
    

    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:

    IE  ⇒ IE
    IE  ⇒ IE
    IE ⇒ IE
    IE ⇒ IE
    IE ⇒ IE
    IE  ⇒ IE
    

    Notice that the mapping T → IE preserves the existence and direction of assignment compatibility. That is, if X ⇒ Y, then it is also true that IE ⇒ IE.

    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:

    { IComparable, 
      IComparable, 
      IComparable, 
      IComparable }
    

    now we have the mapping from the first set to the third set T → IC.

    In C# 4:

    IC  ⇒ IC
    IC ⇒ IC     Backwards!
    IC ⇒ IC
    IC ⇒ IC
    IC  ⇒ IC     Backwards!
    IC  ⇒ IC
    

    That is, the mapping T → IC has preserved the existence but reversed the direction of assignment compatibility. That is, if X ⇒ Y, then IC ⇐ IC.

    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.

提交回复
热议问题