title: How to use Inheritance when using Generic Constraints
body: <p>I'm struggling with some Generic constraint issues when trying to implement a library that allows inheritance and hoping someone can help. </p>
  
  <p>I'm trying to build up a class library that has 3 flavours to it, each building on top of the other. To me it seemed like a perfect opportunity to use Generics as I can't quite do what I want through pure inheritance. The code's below (this should paste straight into VS) with some explanation afterwards:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  
  namespace Test
  {
      #region Base Classes
  
      public class GenericElement { }
  
      /// &lt;summary&gt;Visit to a GenericElement&lt;/summary&gt;
      public class Generic_Visit&lt;E&gt; where E : GenericElement
      {
          public E Element { get; set; }
      }
  
      /// &lt;summary&gt;Collection of Visits&lt;/summary&gt;
      public class Generic_Route&lt;V, E&gt;
          where V : Generic_Visit&lt;E&gt;
          where E : GenericElement
      {
          public List&lt;V&gt; Visits { get; set; }
          public Double Distance { get; set; }
      }
  
      /// &lt;summary&gt;Collection of Routes&lt;/summary&gt;
      public class Generic_Solution&lt;R, V, E&gt;
          where R : Generic_Route&lt;V, E&gt;
          where V : Generic_Visit&lt;E&gt;
          where E : GenericElement
      {
          public List&lt;R&gt; Routes { get; set; }
  
          public Double Distance
          {
              get
              {
                  return this.Routes.Select(r =&gt; r.Distance).Sum();
              }
          }
      }
  
      #endregion
  
      #region TSP Classes
  
      public class Concrete_TSPNode : GenericElement { }
  
      public abstract class Generic_TSPVisit&lt;E&gt; : Generic_Visit&lt;E&gt;
          where E : Concrete_TSPNode
      {
          public Double Time { get; set; }
      }
  
      public abstract class Generic_TSPRoute&lt;V, E&gt; : Generic_Route&lt;V, E&gt;
          where V : Concrete_TSPVisit
          where E : Concrete_TSPNode
      {
          public Double Time
          {
              get
              {
                  return this.Visits.Select(v =&gt; v.Time).Sum();
              }
          }
      }
  
      public abstract class Generic_TSPSolution&lt;R, V, E&gt; : Generic_Solution&lt;R, V, E&gt;
          where R : Concrete_TSPRoute
          where V : Concrete_TSPVisit
          where E : Concrete_TSPNode
      {
          public Double Time
          {
              get
              {
                  return this.Routes.Select(r =&gt; r.Time).Sum();
              }
          }
      }
  
      public class Concrete_TSPVisit : Generic_TSPVisit&lt;Concrete_TSPNode&gt; { }
  
      public class Concrete_TSPRoute : Generic_TSPRoute&lt;Concrete_TSPVisit, Concrete_TSPNode&gt; { }
  
      public class Concrete_TSPSolution : Generic_TSPSolution&lt;Concrete_TSPRoute, Concrete_TSPVisit, Concrete_TSPNode&gt; { }
  
      #endregion
  
      #region VRP
  
      public class Concrete_VRPNode : Concrete_TSPNode { }
  
      public abstract class Generic_VRPVisit&lt;E&gt; : Generic_TSPVisit&lt;E&gt; where E : Concrete_VRPNode
      {
          public Double Capacity { get; set; }
      }
  
      public abstract class Generic_VRPRoute&lt;V, E&gt; : Generic_TSPRoute&lt;V, E&gt;
          where V : Concrete_VRPVisit
          where E : Concrete_VRPNode
      {
          public Double Capacity
          {
              get
              {
                  return this.Visits.Select(v =&gt; v.Capacity).Sum();
              }
          }
      }
  
      public abstract class G_VRPSolution&lt;R, V, E&gt; : Generic_TSPSolution&lt;R, V, E&gt;
          where R : Concrete_VRPRoute
          where V : Concrete_VRPVisit
          where E : Concrete_VRPNode
      {
          public Double Capacity
          {
              get
              {
                  return this.Routes.Select(r =&gt; r.Capacity).Sum();
              }
          }
      }
  
      public class Concrete_VRPVisit : Generic_VRPVisit&lt;Concrete_VRPNode&gt; { }
  
      public class Concrete_VRPRoute : Generic_VRPRoute&lt;Concrete_VRPVisit, Concrete_VRPNode&gt; { }
  
      public class Concrete_VRPSolution : Generic_TSPSolution&lt;Concrete_VRPRoute, Concrete_VRPVisit, Concrete_VRPNode&gt; { }
  
      #endregion
  }
  </code></pre>
  
  <p>The idea behind the code is that there are a set of base classes that expose properties using Generics. This allows me to have strongly typed collections for example.</p>
  
  <p>There are then 2 of the 3 stages build upon these, TSP and VRP in the example which have 4 concrete classes (these are what the developer using the class library should be interacting with as the generic constraints just get a bit crazy) - Element, Visit, Route and Solution.</p>
  
  <p>There are also some classes prefixed Generic for both TSP and VRP. These allow the inheritance that I want as it exposes the Generic Types. If I don't use these (say Concrete_VRPRoute inherits Concrete_TSPRoute) then I have to keep casting the type of item returned by the Visits collection to get the Capacity property for example.</p>
  
  <p>I'm fairly confident all the types line up correctly, but when I try to build I get the following errors and I really don't know how to tackle them.</p>
  
  <blockquote>
    <p>Error 1   The type 'V' cannot be used as
    type parameter 'V' in the generic type
    or method 'Test.Generic_Route'.
    There is no implicit reference
    conversion from 'V' to
    'Test.Generic_Visit'.   </p>
    
    <p>Error 2   The
    type 'V' cannot be used as type
    parameter 'V' in the generic type or
    method 'Test.Generic_Solution'.
    There is no implicit reference
    conversion from 'V' to
    'Test.Generic_Visit'.   </p>
    
    <p>Error 3   The
    type 'R' cannot be used as type
    parameter 'R' in the generic type or
    method 'Test.Generic_Solution'.
    There is no implicit reference
    conversion from 'R' to
    'Test.Generic_Route'  </p>
    
    <p>Error 4   The type 'V' cannot be used as
    type parameter 'V' in the generic type
    or method
    'Test.Generic_TSPRoute'. There is
    no implicit reference conversion from
    'V' to 'Test.Concrete_TSPVisit'.   </p>
    
    <p>Error 5   The type 'V' cannot be used as
    type parameter 'V' in the generic type
    or method
    'Test.Generic_TSPSolution'.
    There is no implicit reference
    conversion from 'V' to
    'Test.Concrete_TSPVisit'.  </p>
    
    <p>Error 6   The
    type 'R' cannot be used as type
    parameter 'R' in the generic type or
    method
    'Test.Generic_TSPSolution'.
    There is no implicit reference
    conversion from 'R' to
    'Test.Concrete_TSPRoute'.  </p>
    
    <p>Error 7   The
    type 'Test.Concrete_VRPVisit' cannot
    be used as type parameter 'V' in the
    generic type or method
    'Test.Generic_TSPSolution'.
    There is no implicit reference
    conversion from
    'Test.Concrete_VRPVisit' to
    'Test.Concrete_TSPVisit'.  </p>
    
    <p>Error 8   The
    type 'Test.Concrete_VRPRoute' cannot
    be used as type parameter 'R' in the
    generic type or method
    'Test.Generic_TSPSolution'.
    There is no implicit reference
    conversion from
    'Test.Concrete_VRPRoute' to
    'Test.Concrete_TSPRoute'.'Test.Concrete_TSPRoute'.        </p>
  </blockquote>