Check if a type is of any from a list of types? I need to check whether a generic type parameter is in a set of valid types and have created extension methods to do a run time check:

public static bool Is(this Type type, params Type[] types) {
  return types.Any(t =&gt; t == type);
}

public static bool Is&lt;T1&gt;(this Type type) {
  return type.Is(typeof (T1));
}

public static bool Is&lt;T1, T2&gt;(this Type type) {
  return type.Is(typeof (T1), typeof (T2));
}


With additional methods for T3 - T#...

Usage (in constructor for the generic class):

if(!typeof(T).Is&lt;Int32, String, Boolean, CustomClass, Whatever&gt;())
    throw new ArgumentException("T must be a type.");


But I would prefer a compile time check (which I don't believe is possible). Failing that, any suggestions on improvements are appreciated.
Here is a run-time and a compile-time approach. For the compile-time approach I only show how it works for 3 type parameters and for 20 type parameters to show the concept. You can easily add more methods/classes for the number of type parameters you need.

Scroll down to the bottom to see some usage examples.

public static class RuntimeTypeCheckExtensions
{
    public static bool IsAssignableToAnyOf(this Type typeOperand, IEnumerable&lt;Type&gt; types)
    {
        return types.Any(type =&gt; type.IsAssignableFrom(typeOperand));
    }

    public static bool IsAssignableToAnyOf(this Type typeOperand, params Type[] types)
    {
        return IsAssignableToAnyOf(typeOperand, types.AsEnumerable());
    }

    public static bool IsAssignableToAnyOf&lt;T1, T2, T3&gt;(this Type typeOperand)
    {
        return typeOperand.IsAssignableToAnyOf(typeof(T1), typeof(T2), typeof(T3));
    }

    public static bool IsAssignableToAnyOf&lt;T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20&gt;(this Type typeOperand)
    {
        return typeOperand.IsAssignableToAnyOf(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15), typeof(T16), typeof(T17), typeof(T18), typeof(T19), typeof(T20));
    }
}

public static class CompileTimeTypeCheckUtils
{
    public static IsAssignableToAnyOfWrapper&lt;T1, T2, T3&gt; IsAssignableToAnyOf&lt;T1, T2, T3&gt;()
    {
        return new IsAssignableToAnyOfWrapper&lt;T1, T2, T3&gt;();
    }

    public static IsAssignableToAnyOfWrapper&lt;T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20&gt; IsAssignableToAnyOf&lt;T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20&gt;()
    {
        return new IsAssignableToAnyOfWrapper&lt;T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20&gt;();
    }
}

public class IsAssignableToAnyOfWrapper&lt;T1, T2, T3&gt;
{
    public void OperandToCheck(T1 operand) { }
    public void OperandToCheck(T2 operand) { }
    public void OperandToCheck(T3 operand) { }
}

public class IsAssignableToAnyOfWrapper&lt;T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20&gt;
{

    public void OperandToCheck(T1 operand) { }
    public void OperandToCheck(T2 operand) { }
    public void OperandToCheck(T3 operand) { }
    public void OperandToCheck(T4 operand) { }
    public void OperandToCheck(T5 operand) { }
    public void OperandToCheck(T6 operand) { }
    public void OperandToCheck(T7 operand) { }
    public void OperandToCheck(T8 operand) { }
    public void OperandToCheck(T9 operand) { }
    public void OperandToCheck(T10 operand) { }
    public void OperandToCheck(T11 operand) { }
    public void OperandToCheck(T12 operand) { }
    public void OperandToCheck(T13 operand) { }
    public void OperandToCheck(T14 operand) { }
    public void OperandToCheck(T15 operand) { }
    public void OperandToCheck(T16 operand) { }
    public void OperandToCheck(T17 operand) { }
    public void OperandToCheck(T18 operand) { }
    public void OperandToCheck(T19 operand) { }
    public void OperandToCheck(T20 operand) { }
}


Usages:

Type someType = ...

// Three example usages of run-time check (using generic types, params and IEnumerable):
if (someType.IsAssignableToAnyOf&lt;string, int, double&gt;())
{
}

if (someType.IsAssignableToAnyOf(typeof(string), typeof(int), typeof(double)))
{
}

IEnumerable&lt;Type&gt; enumerableOfAcceptedTypes = new Type[]
{
    typeof (string),
    typeof (int),
    typeof (double)
};

if (someType.IsAssignableToAnyOf(enumerableOfAcceptedTypes))
{
}

// Two example usages of compile-time check:
CompileTimeTypeCheckUtils.IsAssignableToAnyOf&lt;string, int, long&gt;().OperandToCheck(5); // &lt;-- No compile-time error

CompileTimeTypeCheckUtils.IsAssignableToAnyOf&lt;string, int, long&gt;().OperandToCheck(5F); // &lt;-- Compile-time error