I need to pass a List of Types to a method, but I want to be sure (at compile time that is) that all of them inherit from BaseType. Also, I dont know how many Types have to be passed.
So I figured this would be a bad way to go:
public void DoSomething(params Type[] types)
So what I ended up doing up to now is something like this:
private void DoSomething(params Type[] types)
public void DoSomething<T1>()
where T1 : BaseType
{
DoSomething(typeof(T1));
}
public void DoSomething<T1, T2>()
where T1 : BaseType
where T2 : BaseType
{
DoSomething(typeof(T1), typeof(T2));
}
public void DoSomething<T1, T2, T3>()
where T1 : BaseType
where T2 : BaseType
where T3 : BaseType{...}
// and so on...
You get the Idea. So the Question is: can you do this a bit more beautifully? Because this does not support an arbitrary number of types. And in my scenario, eight or more types would not be too uncommon.
I want to use this for "magic" of this kind but the caller does not have a reference to the container.
There's no way to represent such a constraint in C# (or CIL for that matter), so you're going to either have to struggle through with writing all those overloads, or give up compile-time safety and just check at run-time.
If possible, one other alternative would be to write an overload that can make use of examples. Whether or not this would be useful depends on the domain, really.
public void DoSomething(params BaseClass[] examples)
{
//null-checks here
Type[] types = examples.Select(e => e.GetType())
.ToArray();
//...
}
Usage (let's say the BaseClass
was Mammal
):
// Compiles fine.
DoSomething(new Goat(), new Tiger(), new Lion());
// Won't compile.
DoSomething(new Fish(), new Tiger(), new Lion());
And here's a sample for checking at run-time:
public void DoSomething(Type[] types)
{
//null-checks here
// Or perhaps you want IsSubclassOf...
if(types.Any(t => !typeof(BaseClass).IsAssignableFrom(t))
throw new ArgumentException(...);
}
No, a generic type is defined by the namespace, the class name, and the number of type parameters (i.e. you can't have a class with the same name in the same namespace with the same number of type parameters, even if the constraints on them are different).
If it was possible to have a single class have an undefined number of type parameters, then the framework would have taken advantage of this with the Action<> and Func<> classes, which it doesn't.
精彩评论