Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The question is "what is the difference between covariance and contravariance?"</p> <p>Covariance and contravariance are properties of <em>a mapping function that associates one member of a set with another</em>. More specifically, a mapping can be covariant or contravariant with respect to a <em>relation</em> on that set.</p> <p>Consider the following two subsets of the set of all C# types. First:</p> <pre><code>{ Animal, Tiger, Fruit, Banana }. </code></pre> <p>And second, this clearly related set:</p> <pre><code>{ IEnumerable&lt;Animal&gt;, IEnumerable&lt;Tiger&gt;, IEnumerable&lt;Fruit&gt;, IEnumerable&lt;Banana&gt; } </code></pre> <p>There is a <em>mapping</em> operation from the first set to the second set. That is, for each T in the first set, the <em>corresponding</em> type in the second set is <code>IEnumerable&lt;T&gt;</code>. Or, in short form, the mapping is <code>T → IE&lt;T&gt;</code>. Notice that this is a "thin arrow".</p> <p>With me so far?</p> <p>Now let's consider a <em>relation</em>. There is an <em>assignment compatibility relationship</em> between pairs of types in the first set. A value of type <code>Tiger</code> can be assigned to a variable of type <code>Animal</code>, so these types are said to be "assignment compatible". Let's write "a value of type <code>X</code> can be assigned to a variable of type <code>Y</code>" in a shorter form: <code>X ⇒ Y</code>. Notice that this is a "fat arrow".</p> <p>So in our first subset, here are all the assignment compatibility relationships:</p> <pre><code>Tiger ⇒ Tiger Tiger ⇒ Animal Animal ⇒ Animal Banana ⇒ Banana Banana ⇒ Fruit Fruit ⇒ Fruit </code></pre> <p>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:</p> <pre><code>IE&lt;Tiger&gt; ⇒ IE&lt;Tiger&gt; IE&lt;Tiger&gt; ⇒ IE&lt;Animal&gt; IE&lt;Animal&gt; ⇒ IE&lt;Animal&gt; IE&lt;Banana&gt; ⇒ IE&lt;Banana&gt; IE&lt;Banana&gt; ⇒ IE&lt;Fruit&gt; IE&lt;Fruit&gt; ⇒ IE&lt;Fruit&gt; </code></pre> <p>Notice that the mapping <code>T → IE&lt;T&gt;</code> <em>preserves the existence and direction of assignment compatibility</em>. That is, if <code>X ⇒ Y</code>, then it is also true that <code>IE&lt;X&gt; ⇒ IE&lt;Y&gt;</code>. </p> <p>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.</p> <p>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.</p> <p>That's covariance. Now consider this subset of the set of all types:</p> <pre><code>{ IComparable&lt;Tiger&gt;, IComparable&lt;Animal&gt;, IComparable&lt;Fruit&gt;, IComparable&lt;Banana&gt; } </code></pre> <p>now we have the mapping from the first set to the third set <code>T → IC&lt;T&gt;</code>.</p> <p>In C# 4:</p> <pre><code>IC&lt;Tiger&gt; ⇒ IC&lt;Tiger&gt; IC&lt;Animal&gt; ⇒ IC&lt;Tiger&gt; Backwards! IC&lt;Animal&gt; ⇒ IC&lt;Animal&gt; IC&lt;Banana&gt; ⇒ IC&lt;Banana&gt; IC&lt;Fruit&gt; ⇒ IC&lt;Banana&gt; Backwards! IC&lt;Fruit&gt; ⇒ IC&lt;Fruit&gt; </code></pre> <p>That is, the mapping <code>T → IC&lt;T&gt;</code> has <em>preserved the existence but reversed the direction</em> of assignment compatibility. That is, if <code>X ⇒ Y</code>, then <code>IC&lt;X&gt; ⇐ IC&lt;Y&gt;</code>.</p> <p>A mapping which <em>preserves but reverses</em> a relation is called a <em>contravariant</em> mapping.</p> <p>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.</p> <p>So that's the difference between covariance and contravariance in C# 4. Covariance <em>preserves</em> the direction of assignability. Contravariance <em>reverses</em> it.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload