title: Covariance and contravariance, compile time errors
body: <p>I've been reading up on covariance and contravariance - <a href="http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29" rel="nofollow noreferrer">Wikipedia</a> talks about the following:</p>
  <blockquote>
  <p>Suppose you have a class representing a person. A person can see the doctor, so this class might have a method virtual void Person::see(Doctor d). Now suppose you want to make a subclass of the Person class, Child. That is, a Child is a Person. One might then like to make a subclass of Doctor, Pediatrician. If children only visit pediatricians, we would like to enforce that in the type system. However, a naive implementation fails: because a Child is a Person, Child::see(d) must take any Doctor, not just a Pediatrician.</p>
  </blockquote>
  <p>Here is a &quot;naive implementation&quot;:</p>
  <pre><code>public interface IDoctor
  {
  }
  
  public interface IPerson
  {
      void VisitDoctor(IDoctor doctor);
  }
  
  public class Adult : IPerson
  {
      public void VisitDoctor(IDoctor doctor)
      {
          Console.WriteLine(&quot;Adult saw doctor of type: {0}&quot;, doctor.GetType().Name);
      }
  }
  
  public class Child : IPerson
  {
      public void VisitDoctor(IDoctor doctor)
      {
          Console.WriteLine(&quot;Child saw doctor of type: {0}&quot;, doctor.GetType().Name);
      }
  }
  
  public class AdultDoctor : IDoctor
  {
  }
  
  public class ChildDoctor : IDoctor
  {
  }
  </code></pre>
  <p>These tests:</p>
  <pre><code>[Test]
  public void AdultSeesDoctor()
  {
      var adult = new Adult();
      adult.VisitDoctor(new AdultDoctor());
      adult.VisitDoctor(new ChildDoctor());  // &lt;-- Would like this to fail
  }
  
  [Test]
  public void ChildSeesDoctor()
  {
      var child = new Child();
      child.VisitDoctor(new AdultDoctor());  // &lt;-- Would like this to fail
      child.VisitDoctor(new ChildDoctor());
  }
  </code></pre>
  <p>Output:</p>
  <blockquote>
  <p>Adult saw doctor of type: AdultDoctor</p>
  <p>Adult saw doctor of type: ChildDoctor</p>
  <p>Child saw doctor of type: AdultDoctor</p>
  <p>Child saw doctor of type: ChildDoctor</p>
  </blockquote>
  <p>Now, I can implement the following, which throws a runtime error if an adult tries to visit a child doctor, or if a child tries to visit an adult doctor (throws a <code>System.InvalidCastException</code>):</p>
  <pre><code>public interface IVisitDoctors&lt;T&gt; where T : IDoctor
  {
      void VisitDoctor(T doctor);
  }
  
  public class Child : IPerson
  {
      private readonly ChildDoctorVisitor _cdv = new ChildDoctorVisitor();
  
      public void VisitDoctor(IDoctor doctor)
      {
          _cdv.VisitDoctor((ChildDoctor)doctor);
      }
  }
  
  public class Adult : IPerson
  {
      private readonly AdultDoctorVisitor _adv = new AdultDoctorVisitor();
  
      public void VisitDoctor(IDoctor doctor)
      {
          _adv.VisitDoctor((AdultDoctor)doctor);
      }
  }
  </code></pre>
  <p>Could you force classes of <code>Adult</code> to only visit doctors of type <code>AdultDoctor</code>, such that a <em>compile-time</em> error is thrown if a doctor of type <code>ChildDoctor</code> is visited (and vice versa for classes of <code>Child</code>)?</p>