C#:在同一个泛型变量上是否可能有多个泛型约束?
用一个例子来说明这一点:C#:在同一个泛型变量上是否可能有多个泛型约束?,c#,generics,C#,Generics,用一个例子来说明这一点: ??? public class Foo<T> where T:(ClassA || ClassB){} ???公共类Foo其中T:(ClassA | | ClassB){} 是否可以对or关系中的许多不相关的类限制T(T是ClassA或ClassB,但不是别的),或者实现这一点的唯一方法是 使ClassA和ClassB都实现相同的接口 使两个类都派生自同一基类 并将其用作约束条件 因此,为了澄清问题:我的问题并不关心是否可以为n个变量设置n
??? public class Foo<T> where T:(ClassA || ClassB){}
???公共类Foo其中T:(ClassA | | ClassB){}
是否可以对or关系中的许多不相关的类限制T(T是ClassA或ClassB,但不是别的),或者实现这一点的唯一方法是
- 使ClassA和ClassB都实现相同的接口
- 使两个类都派生自同一基类
因此,为了澄清问题:我的问题并不关心是否可以为n个变量设置n个通用约束,我想知道是否可以为同一个变量设置n个约束。不,如果你仔细想想,它不会很有用 应用泛型约束的目的是确保代码能够对类型执行某些操作。例如,
new()
约束确保您可以执行new T()
,这对于无约束类型是不可能的。但是应用“或”约束并不能为T
提供任何有用的静态保证,因此您不能真正将其用于任何事情
但是,对于单个类型的变量,您可以有多个约束,但它们是“和”约束,即它们都必须满足。简短的回答是:不,您不能。其他人已经解释了原因,但简而言之,您将失去泛型附带的类型安全性
如果出于任何原因您仍然需要它,那么有一个解决方案可以使用方法重载,而编译器将完成其余的工作
public void Foo<T>(T instance) where T : ClassA
{
GenericFoo(instance);
}
public void Foo<T>(T instance) where T : ClassB
{
GenericFoo(instance);
}
private void GenericFoo(object instance)
{
// Do stuff
}
公共void Foo(T实例),其中T:ClassA
{
GenericFoo(实例);
}
公共void Foo(T实例),其中T:ClassB
{
GenericFoo(实例);
}
私有void GenericFoo(对象实例)
{
//做事
}
我将为两者实现不同类型的逻辑,并返回适当的。当然,这可以通过使用接口来完成
即使您可以保证这两种类型具有完全相同的成员,编译器也无法验证这一点
通过让两个类实现相同的接口,您可以向编译器保证它们至少共享接口的成员,并且这些成员可供泛型类使用。这就是接口存在的原因,也是泛型的全部要点。如果我理解正确,您基本上希望将表达式作为约束的一部分进行求值,据我所知,这是不可能的 但类型参数可以有多个约束,只是不能作为表达式。请参见以下内容:
class EmployeeList,其中T:Employee,ieemployee,System.IComparable,new()
{
// ...
}
这里T
sure有多个约束,但不是作为表达式
在这种情况下,您可能希望查看一下您的设计,以消除您的问题 没有或者,您所能做的就是对基类或接口进行约束。如果可能,您将如何处理不在ClassB中的ClassA.Foo?当成员名称相同但类型不同时会发生什么?@markbenningfield:这个问题是关于约束两个不同的类型参数。这是一个关于对一个类型参数应用两个约束的问题。请参见此问题的答案@BoltClock:我已经撤销了该标志,但我知道我以前看到过这个问题。@HenkHolterman:我的问题本质上是理论性的,尽管我可以想象这样的情况:我的类可以处理返回相同结果的两个不相关的类。我将为两者实现不同类型的逻辑,并返回适当的。当然,这可以通过接口来实现。我知道,我只是出于好奇问:)为什么建议使用编译时类型安全方法来调用
对象
重载?只需完全删除这些泛型,因为对象
是私有的,现在我可以保证该对象是ClassA
或ClassB
,正如OP所要求的那样。我不会这样做,我只是回答了这个问题。“使用方法重载,编译器完成其余的工作”编译器在这里除了编译代码之外什么都不做…它确实根据类型约束选择了正确的方法签名,因此在代码Foo(new ClassA())
和Foo(new ClassB())
可以工作,但是Foo(new ClassC())
不会编译,这正是OP所要求的。请注意,在问题中,Foo是一个类,而不是一个方法,因此需要注意将泛型从一个类移动到另一个方法。
class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
// ...
}