我有一个带有通用参数的方法:
internal void DoSomething<T>(T workWithThis)
{
}
我现在想要限制此方法只接受继承我想指定的几个接口之一的参数。但是我还没有找到办法。我想要的是这样的:
internal void DoSomething<T>(T workWithThis) where T : ISomething | ISomethingElse
{
}
显然这不起作用,所以我尝试用静态方法来检查T的类型:
public static bool CheckType(Type t)
{
return */check here*/
}
internal void DoSomething<T>(T workWithThis) where T : CheckType(typeof(T))
{
}
显然这也行不通。问题是为什么?为什么编译器阻止我这样做,基于我的理解,没有理由不使用
答案 0 :(得分:5)
为什么编译器阻止我这样做,基于我的理解,没有理由不这样做
编译器阻止您这样做,因为您尝试执行C#作为语言不支持的操作。您尝试使用的语法不符合C#规范第10.1.5节中的产品。
C#作为一种语言根本不支持您需要的方案。
现在为什么这种语言不允许这种灵活性 - 这归结为正常的平衡行为:
哦,当然这不只是C# - CLR也必须支持这样的限制,它至少会鼓励其他CLR语言理解它。
我建议您通过两种不同的方法来解决这个问题。请注意,它们不能只是泛型方法的重载,因为重载只能通过泛型类型约束来区分。如果你不介意拳击实现接口的值类型,你可以重载:
internal void DoSomething(ISomething something)
{
}
internal void DoSomething(ISomethingElse somethingElse)
{
}
...虽然如果你传入一个表达式是实现两个接口的类型,你最终会出现过载歧义。
或者,只需给这两种方法命名不同。
答案 1 :(得分:2)
编译器必须在编译时验证所有约束,并且不能调用方法来执行此操作。
您可以在where
约束中指定的唯一内容是:
new()
- 需要无参数构造函数class
- 必须是参考类型struct
- 必须是值类型SomeBaseClass
ISomeInterface
T : U
- 必须是,继承或实施其他通用参数之一有关详细信息,请参阅C# Programming Guide - Constraints on Type Parameters。
至于为什么,你永远不应该回答“我认为没有理由这样做”。你必须从相反的方向开始,“为什么要这样做”,然后提出足够的合理和现实的场景和要求,使其值得实施。见Eric Gunnerson的Minus 100 Points。
要在代码中修复此问题,您应该从公共接口派生这两个接口,并在其上添加约束。
如果这两个接口没有任何共同之处,那么我首先会质疑实际添加约束的好处。
例如,如果您的代码要调用与泛型类型/方法一起使用的对象上的方法,那么显然两个接口必须具有相同的概念,该方法是什么,并且唯一的方法是将用于在公共基础接口中定义的方法。这两个接口碰巧具有相同的方法或属性,具有相同的签名,并不会使它成为相同的方法。
话虽如此,您确定在这里需要泛型吗?
如何宣布两个方法,每个方法都采用一个这样的接口?
internal void DoSomething(ISomething workWithThis)
internal void DoSomething(ISomethingElse workWithThis)
答案 2 :(得分:1)
编译器使用泛型约束来确定泛型方法中T上可用的操作 - 因此允许或表达式不是类型安全的。例如,您有两个接口IFirst
和ISecond
:
public interface IFirst
{
void First();
}
public interface ISecond
{
void Second();
}
internal void DoSomething<T>(T workWithThis) where T : IFirst or ISecond
{
//How to call this method if the type is ISecond
workWithThis.First();
//How to call this method if the type is IFirst
workWithThis.Second();
}
答案 3 :(得分:0)
您可以定义一个包含所有这些内容的空接口。
请记住,在C#
接口中可以具有多重继承。
例如:
public interface IHolder : ISomething, ISomethingElse
{
}
和通用
internal void DoSomething<T>(T workWithThis) where T : IHolder
{
}