title: Variance rules in C#
body: <p>The <a href="http://blogs.msdn.com/b/ericlippert/archive/2009/12/03/exact-rules-for-variance-validity.aspx" rel="nofollow">Exact rules for variance validity</a> 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. </p>
  
  <p>A type is <strong>valid covariantly</strong> if it is: </p>
  
  <blockquote>
    <p>1) a pointer type, or a non-generic type. </p>
  </blockquote>
  
  <p>Pointers and non-generic types are not variant in C#, except for arrays and non-generic delegates. Generic classes, structs and enums are invariant. Am I right here? </p>
  
  <blockquote>
    <p>2) An array type T[] where T is valid covariantly. </p>
  </blockquote>
  
  <p>So this means that if the element type <code>T</code> of an array <code>T[]</code> is covariant (reference or array element type), then the array is covariant, and if the element type is invariant (value type), then the Array type is invariant. Arrays cannot be contravariant in C#. Am I right here? </p>
  
  <blockquote>
    <p>3) A generic type parameter type, if it was not declared as being contravariant. </p>
  </blockquote>
  
  <p>We normally say that a generic type is variant on a parameter type, but for a parameter type to be variant on it's own. Is this another short form for saying that? for example, the generic type <code>T&lt;out D&gt;</code> is covariant on <code>D</code> (hence covariantly valid), hence we can say that the type parameter <code>D</code> is covariantly valid. Am I right? </p>
  
  <blockquote>
    <p>4) A constructed class, struct, enum, interface or delegate type X might be valid covariantly. To determine if it is, we examine each type argument differently, depending on whether the corresponding type parameter was declared as covariant (out), contravariant (in), or invariant (neither). (Of course the generic type parameters of classes and structs will never be declared 'out' or 'in'; they will always be invariant.) If the ith type parameter was declared as covariant, then Ti must be valid covariantly. If it was declared as contravariant, then Ti must be valid contravariantly. If it was declared as invariant, then Ti must be valid invariantly. </p>
  </blockquote>
  
  <p><strong>This last rule, from top to bottom, is utterly ambiguous.</strong> </p>
  
  <p>Are we talking about a generic type's variance on all of its in/out/invariant type parameters? By definition, A generic type can be covariant/contravariant/invariant on one type paramter at a time. To be covariant or invariant, in this case, on all of it's type parameters at once doesn't hold any meaning. What could that mean? </p>
  
  <p>Moving forward. To determine if the generic type is covariantly valid, we examine its type arguments <strong>(not type paramters)</strong>. So if the corresponding type parameter is covariant/contravariant/invariant, then the type argument is valid covariantly/contravariantly/invariantly respectively ...</p>
  
  <p>I need this rule be explained in more depth. </p>
  
  <hr>
  
  <p>Edit: Thanks Eric. Greatly appreciated!</p>
  
  <p>I do perfectly understand what valid covariantly/contravariantly/invariantly mean. A type is valid covriantly, if it's definitely not contravariant, which means that it can be invariant. perfectly fine!</p>
  
  <p>For the 4th rule, you follow the procedure of how to determine whether a constructed generic type is valid covariantly, as defined in the rule. But, how do you determine if a type argument that's declared as covariant (out) is covariantly valid? </p>
  
  <p>For example, in the <strong>closed constructed interface I { }</strong> of the <strong>generic interface I { ... }</strong>, <strong>shouldn't the very fact</strong> that the type argument <code>object</code> is declared as a <strong>covariant type parameter(out U)</strong> in the generic interface declaration mean that the type argument object is covariant? I think it should. Cuz that's the very definition of being covariant. </p>
  
  <p>Also, the second rule: </p>
  
  <blockquote>
    <p>2) An array type T[] where T is valid covariantly. </p>
  </blockquote>
  
  <p>What does <strong>the array element type <code>T</code> being valid covariantly</strong> mean? Do you mean the element type being a <strong>value type</strong> (invariant in this case) or a reference type (covariant in this case)? </p>
  
  <p>Cuz the projection <code>T</code> &rarr; <code>T[]</code> is only variant if <code>T</code> is reference type. </p>