[英]Constraint on params array of Types
In the following method: 在以下方法中:
public void Foo(params Type[] types) {}
How can I constrain the types
so that each Type
passed in must derive from a certain base class? 如何约束
types
以便传入的每个Type
必须派生自某个基类?
I want something along the lines of this: 我想要一些与此类似的东西:
public void Foo(params Type[] types) where each types : BaseClass {}
Clarification: 澄清:
I want the types of the classes that derive from BaseClass
, not the instances of them. 我想要从
BaseClass
派生的类的类型 ,而不是它们的实例。
For example if Bar
is a subclass of BaseClass
, I want to be able to pass in typeof(Bar)
, not new Bar()
. 例如,如果
Bar
是BaseClass
的子类,我希望能够传入typeof(Bar)
而不是new Bar()
。
If you want to pass an array of Type
objects, than you can't do what you want. 如果要传递
Type
对象数组,那么您将无法做自己想做的事情。 That's because constraints are part of the type system - you can set a method to get an argument of type int
, or a generic method to receive a generic type parameter derived from IDisposable
, or whatever, but what you have there is already a specific, concrete type - Type
. 这是因为约束是类型系统的一部分-您可以设置一个方法来获取
int
类型的参数,或者设置一个通用方法来接收从IDisposable
派生的通用类型参数,或者其他任何东西,但是您已经拥有了一个特定的,具体Type
。
Type
, confusingly, isn't part of the type system . Type
,容易混淆,是不是类型系统的一部分。 It's just a regular class that happens to describe the type system metadata . 这只是一个描述类系统元数据的常规类。 But it's just any old class.
但这只是任何旧的类。
Being able to constrain a method to only accept a Type
instance whose BaseClass
property is MyBaseClass
is just like being able to constrain a method to only accept string
arguments whose Length == 3
- it's not a question of type (as C# sees it), but of data inside those types. 能够约束一个方法仅接受
BaseClass
属性为MyBaseClass
的Type
实例,就像能够约束一个方法仅接受Length == 3
string
参数-这不是类型的问题(如C#所见),但是这些类型里面的数据 。
Of course, it's not unheard of in other languages to be able to create constrained types - to create a type TLA
which is a type of string
which must be of length 3 - but that's not how C#'s type system (currently) works. 当然,在其他语言中创建约束类型并不是闻所未闻-创建类型
TLA
,它是必须长度为3的string
类型-但这不是C#的类型系统(当前)的工作方式。
What you can do is use generic type parameters as a wrapper: 您可以做的是使用通用类型参数作为包装器:
public void Foo<T1, T2, T3>() where T1 : BaseClass, T2:BaseClass, T3:BaseClass
{
// call untyped Foo.
Foo(typeof(T1), typeof(T2), typeof(T3));
}
This gives you stronger type safety for some scenarios, but it won't give you the ability to pass an unbounded list of types that a params []
will. 在某些情况下,这可以为您提供更强的类型安全性,但无法使您传递
params []
可以实现的无限类型列表。
This is conceptually similar to wrapping a method which accepts an object
parameter with a typed wrapper method. 从概念上讲,这类似于使用类型化包装器方法包装接受
object
参数的方法。 If your Add(object obj)
is confusing, hide it and expose Add(int i) { Add((object)i);}
and Add(string s) { Add((object)s);}
如果您的
Add(object obj)
令人困惑,请将其隐藏并公开Add(int i) { Add((object)i);}
和Add(string s) { Add((object)s);}
The usual 'kind of workaround' here is to check types that are passed to the method and throw an exception if certain type is not what we expect it to be : 通常的“解决方法”是检查传递给方法的类型,如果某些类型不是我们期望的类型,则抛出异常:
public void Foo(params Type[] types)
{
EnsureInheritedFrom<BaseClass>(types);
// ...rest of stuff
}
private void EnsureInheritedFrom<TBaseType>(IEnumerable<Type> types)
{
var targetType = typeof(TBaseType);
foreach(Type type in types)
{
if(!targetType.IsAssignbableFrom(type))
{
throw new ArgumentException(nameof(types), "Type {type.Name} is not supported!");
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.