patterncsharpMinor
Check if a type is of any from a list of types?
Viewed 0 times
fromanytypetypeslistcheck
Problem
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:
With additional methods for T3 - T#...
Usage (in constructor for the generic class):
But I would prefer a compile time check (which I don't believe is possible). Failing that, any suggestions on improvements are appreciated.
public static bool Is(this Type type, params Type[] types) {
return types.Any(t => t == type);
}
public static bool Is(this Type type) {
return type.Is(typeof (T1));
}
public static bool Is(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())
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.
Solution
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.
Usages:
Scroll down to the bottom to see some usage examples.
public static class RuntimeTypeCheckExtensions
{
public static bool IsAssignableToAnyOf(this Type typeOperand, IEnumerable types)
{
return types.Any(type => type.IsAssignableFrom(typeOperand));
}
public static bool IsAssignableToAnyOf(this Type typeOperand, params Type[] types)
{
return IsAssignableToAnyOf(typeOperand, types.AsEnumerable());
}
public static bool IsAssignableToAnyOf(this Type typeOperand)
{
return typeOperand.IsAssignableToAnyOf(typeof(T1), typeof(T2), typeof(T3));
}
public static bool IsAssignableToAnyOf(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 IsAssignableToAnyOf()
{
return new IsAssignableToAnyOfWrapper();
}
public static IsAssignableToAnyOfWrapper IsAssignableToAnyOf()
{
return new IsAssignableToAnyOfWrapper();
}
}
public class IsAssignableToAnyOfWrapper
{
public void OperandToCheck(T1 operand) { }
public void OperandToCheck(T2 operand) { }
public void OperandToCheck(T3 operand) { }
}
public class IsAssignableToAnyOfWrapper
{
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())
{
}
if (someType.IsAssignableToAnyOf(typeof(string), typeof(int), typeof(double)))
{
}
IEnumerable enumerableOfAcceptedTypes = new Type[]
{
typeof (string),
typeof (int),
typeof (double)
};
if (someType.IsAssignableToAnyOf(enumerableOfAcceptedTypes))
{
}
// Two example usages of compile-time check:
CompileTimeTypeCheckUtils.IsAssignableToAnyOf().OperandToCheck(5); // ().OperandToCheck(5F); // <-- Compile-time errorCode Snippets
public static class RuntimeTypeCheckExtensions
{
public static bool IsAssignableToAnyOf(this Type typeOperand, IEnumerable<Type> types)
{
return types.Any(type => type.IsAssignableFrom(typeOperand));
}
public static bool IsAssignableToAnyOf(this Type typeOperand, params Type[] types)
{
return IsAssignableToAnyOf(typeOperand, types.AsEnumerable());
}
public static bool IsAssignableToAnyOf<T1, T2, T3>(this Type typeOperand)
{
return typeOperand.IsAssignableToAnyOf(typeof(T1), typeof(T2), typeof(T3));
}
public static bool IsAssignableToAnyOf<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>(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<T1, T2, T3> IsAssignableToAnyOf<T1, T2, T3>()
{
return new IsAssignableToAnyOfWrapper<T1, T2, T3>();
}
public static IsAssignableToAnyOfWrapper<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20> IsAssignableToAnyOf<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>()
{
return new IsAssignableToAnyOfWrapper<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>();
}
}
public class IsAssignableToAnyOfWrapper<T1, T2, T3>
{
public void OperandToCheck(T1 operand) { }
public void OperandToCheck(T2 operand) { }
public void OperandToCheck(T3 operand) { }
}
public class IsAssignableToAnyOfWrapper<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>
{
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) { }
}Type someType = ...
// Three example usages of run-time check (using generic types, params and IEnumerable):
if (someType.IsAssignableToAnyOf<string, int, double>())
{
}
if (someType.IsAssignableToAnyOf(typeof(string), typeof(int), typeof(double)))
{
}
IEnumerable<Type> enumerableOfAcceptedTypes = new Type[]
{
typeof (string),
typeof (int),
typeof (double)
};
if (someType.IsAssignableToAnyOf(enumerableOfAcceptedTypes))
{
}
// Two example usages of compile-time check:
CompileTimeTypeCheckUtils.IsAssignableToAnyOf<string, int, long>().OperandToCheck(5); // <-- No compile-time error
CompileTimeTypeCheckUtils.IsAssignableToAnyOf<string, int, long>().OperandToCheck(5F); // <-- Compile-time errorContext
StackExchange Code Review Q#34041, answer score: 3
Revisions (0)
No revisions yet.