title: User-defined compile-time type constraints in C#
body: <p>I'm currently experimenting with generics in C#, and came up with the following challenge to myself:</p>
  
  <p>Given a generic function <code>f&lt;T&gt;</code>, validate during compile time that T is a type from a given set [T1, T2, ..., Tn]. For instance, if in <code>f&lt;T&gt;</code> we have</p>
  
  <pre><code>CompileTimeAssert&lt;T&gt;.isContainedIn&lt;TypeList&lt;string, int, bool&gt;&gt;();
  </code></pre>
  
  <p>then <code>f&lt;int&gt;</code> should compile, and <code>f&lt;double&gt;</code> should not compile.</p>
  
  <p>I'm not quite there yet. This is what I have so far:</p>
  
  <pre><code>interface ContainsType&lt;T&gt; {}
  
  class TypeList&lt;T1&gt;: ContainsType&lt;T1&gt; {} 
  class TypeList&lt;T1, T2&gt;: TypeList&lt;T2&gt;, ContainsType&lt;T1&gt;  {}
  class TypeList&lt;T1, T2, T3&gt;: TypeList&lt;T2, T3&gt;, ContainsType&lt;T1&gt; {}
  class TypeList&lt;T1, T2, T3, T4&gt;: TypeList&lt;T2, T3, T4&gt;, ContainsType&lt;T1&gt; {}
  // add longer type lists to taste
  
  class CompileTimeAssert&lt;T&gt;
  {
      public static void isContainedIn&lt;TypeList&gt;()
          where TypeList: ContainsType&lt;T&gt; {}
      public static void isContainedIn&lt;TypeList&gt;(TypeList tl)
          where TypeList: ContainsType&lt;T&gt; {}
  }
  </code></pre>
  
  <p>Given the code above, the following compiles (as expected):</p>
  
  <pre><code> // uses first overload
  CompileTimeAssert&lt;int&gt;.isContainedIn&lt;TypeList&lt;string, int, bool&gt;&gt;();
  
  var myTypeList = new TypeList&lt;string, bool&gt;();
  CompileTimeAssert&lt;string&gt;.isContainedIn(myTypeList); // uses second overload
  </code></pre>
  
  <p>And the following does not compile, also as expected:</p>
  
  <pre><code>CompileTimeAssert&lt;short&gt;.isContainedIn&lt;TypeList&lt;string, int, bool&gt;&gt;();
  
  var myTypeList = new TypeList&lt;string, bool&gt;();
  CompileTimeAssert&lt;double&gt;.isContainedIn(myTypeList);
  </code></pre>
  
  <p>That's all very cute, but also useless. It would become much more useful if one could do the following:</p>
  
  <pre><code>void f&lt;T&gt;()
  {
      CompileTimeAssert&lt;T&gt;.isContainedIn&lt;TypeList&lt;string, int, bool&gt;&gt;();
  }
  </code></pre>
  
  <p>and then have <code>f&lt;int&gt;</code> compile, and <code>f&lt;double&gt;</code> result in a compilation error.</p>
  
  <p>Alas, <code>f&lt;T&gt;</code> as given above fails to compile (regardless of any calls with concrete types).
  I'm getting the following error (using MonoDevelop on Mac OS X):</p>
  
  <blockquote>
    <p>Error CS0311: The type <code>TypeList&lt;string,int,bool&gt;' cannot be used as type parameter
    'TypeList' in the generic type or method 'CompileTimeAssert&lt;T&gt;.isContainedIn&lt;TypeList&gt;()'.
    There is no implicit reference conversion from</code>TypeList' to
    'ContainsType'</p>
  </blockquote>
  
  <p>I kind of understand why this doesn't work, but so far, I haven't been able to come up with a working alternative. Does anyone have any ideas on whether what I want is possible at all in C#?</p>
  
  <p>Thanks.</p>