title: Why is "dynamic" not covariant and contravariant with respect to all types when used as a generic type parameter?
body: <p>I am wondering if <code>dynamic</code> is semantically equivalent to <code>object</code> when used as a generic type parameter. If so, I am curious why this limitation exists since the two are different when assigning values to variables or formal parameters.</p>
  
  <p>I've written a small experiment in C# 4.0 to tease apart some of the details. I defined some simple interfaces and implementations:</p>
  
  <pre><code>interface ICovariance&lt;out T&gt; { T Method(); }
  
  interface IContravariance&lt;in T&gt; { void Method(T argument); }
  
  class Covariance&lt;T&gt; : ICovariance&lt;T&gt;
  {
      public T Method() { return default(T); }
  }
  
  class Contravariance&lt;T&gt; : IContravariance&lt;T&gt;
  {
      public void Method(T argument) { }
  }
  </code></pre>
  
  <p>The interesting details of the experiment:</p>
  
  <pre><code>class Variance
  {
      static void Example()
      {
          ICovariance&lt;object&gt; c1 = new Covariance&lt;string&gt;();
          IContravariance&lt;string&gt; c2 = new Contravariance&lt;object&gt;();
  
          ICovariance&lt;dynamic&gt; c3 = new Covariance&lt;string&gt;();
          IContravariance&lt;string&gt; c4 = new Contravariance&lt;dynamic&gt;();
  
          ICovariance&lt;object&gt; c5 = new Covariance&lt;dynamic&gt;();
          IContravariance&lt;dynamic&gt; c6 = new Contravariance&lt;object&gt;();
  
          // The following statements do not compile.
          //ICovariance&lt;string&gt; c7 = new Covariance&lt;dynamic&gt;();
          //IContravariance&lt;dynamic&gt; c8 = new Contravariance&lt;string&gt;();
  
          // However, these do.
          string s = new Covariance&lt;dynamic&gt;().Method();
          new Contravariance&lt;string&gt;().Method((dynamic)s);       
      }
  }
  </code></pre>
  
  <p>The first two statements with <code>c1</code> and <code>c2</code> demonstrate that basic covariance and contravariance are working. I then use <code>c3</code> and <code>c4</code> to show that <code>dynamic</code> can be used as a generic type parameter in the same fashion.</p>
  
  <p>The statements with <code>c5</code> and <code>c6</code> reveal that a conversion from <code>dynamic</code> to <code>object</code> is always valid. This isn't really too surprising, since <code>object</code> is an ancestor of all other types.</p>
  
  <p>The final experiment with <code>c7</code> and <code>c8</code> is where I start to become confused. It implies that methods that return <code>dynamic</code> objects are not substitutes for methods that return <code>string</code> ones, and similarly that methods that accept <code>string</code> objects cannot take <code>dynamic</code> ones. The final two statements with the assignment and method call show this is clearly not the case, hence my confusion.</p>
  
  <p>I thought about this a little, and wondered if this is to prevent programmers from using <code>ICovariance&lt;dynamic&gt;</code> as a stepping stone between type conversions that would result in run-time errors, such as:</p>
  
  <pre><code>ICovariance&lt;dynamic&gt; c9 = new Covariance&lt;Exception&gt;();
  ICovariance&lt;string&gt; c10 = c9;
  // While this is definitely not allowed:
  ICovariance&lt;string&gt; c11 = new Covariance&lt;Exception&gt;();
  </code></pre>
  
  <p>However, this is unconvincing in the case of <code>dynamic</code> since we lose type-safety anyway:</p>
  
  <pre><code>dynamic v1 = new Exception();
  string  v2 = v1;
  </code></pre>
  
  <p>Put another way, the question is <strong>"Why does the semantics of <code>dynamic</code> differ between assignment and covariance/contravariance with generics?"</strong></p>