You cannot force the compiler to do the compile-time check for you without using generics. Since generics do not provide variadic syntax for dealing with this kind of type parameter lists, a common workaround is to provide multiple overloads of a generic with different number of type parameters, and then call a common implementation:
void myFunction(string t) {
myFunctionImpl(t, new Type[0]);
}
void myFunction<T0>(string t) where T0:IMyInterface {
myFunctionImpl(t, new[] { typeof(T0) });
}
void myFunction<T0,T1>(string t) where T0:IMyInterface,
T1:IMyInterface {
myFunctionImpl(t, new[] { typeof(T0), typeof(T1) });
}
...
void myFunction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>(string t)
where T0:IMyInterface,
T1:IMyInterface,
T2:IMyInterface,
T3:IMyInterface,
T4:IMyInterface,
T5:IMyInterface,
T6:IMyInterface,
T7:IMyInterface,
T8:IMyInterface,
T9:IMyInterface {
myFunctionImpl(t, new[] { typeof(T0), typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9) });
}
This approach lets you call myFunction
with up to ten type parameters as needed.