通用方法多个(OR)types的约束

读这个 ,我知道有可能允许一个方法接受多种types的参数,使其成为一种通用的方法。 在示例中,下面的代码与types约束一起使用,以确保“U”是一个IEnumerable<T>

 public T DoSomething<U, T>(U arg) where U : IEnumerable<T> { return arg.First(); } 

我发现了一些允许添加多个types约束的代码,例如:

 public void test<T>(string a, T arg) where T: ParentClass, ChildClass { //do something } 

但是,这段代码似乎强制arg必须是一个ParentClass ChildClasstypes。 我想要做的就是说,arg可以是一种ParentClass ChildClasstypes, ParentClass

 public void test<T>(string a, T arg) where T: string OR Exception { //do something } 

你的帮助是一如既往的赞赏!

这是不可能的。 但是,您可以为特定types定义重载:

 public void test(string a, string arg); public void test(string a, Exception arg); 

如果这些是generics类的一部分,那么它们将优于genericstypes的方法。

Botz答案是100%正确的,这里是一个简短的解释:

当你正在写一个方法(通用或不是),并声明方法所需的参数types时,你正在定义一个合约:

如果你给我一个知道如何做typesT知道该怎么做的事情的对象,我可以提供'a':我声明的types的返回值,或'b':某种使用那种types。

如果你尝试一次给予多于一种types(通过拥有一个或者)或者试图让它返回一个可能超过一种契约变得模糊的types的值:

如果你给我一个知道如何跳绳或知道如何计算pi到第15位的物体,我会返回一个可以去钓鱼的物体,或者混合混凝土。

问题是,当你进入方法时,你不知道他们是否给了你一个IJumpRope或者一个PiFactory 。 而且,当你继续使用这个方法时(假设你已经知道这个方法是神奇地编译的),你不确定你是否有一个FisherAbstractConcreteMixer 。 基本上它使整个事情更混乱。

解决您的问题是两种可能性之一:

  1. 定义多个方法来定义每个可能的转换,行为或其他。 这是Botz的答案。 在编程领域,这被称为重载方法。

  2. 定义一个知道如何完成方法所需的所有事情的基类或接口,并且只有一种方法可以使用该types。 这可能涉及在一个小类中包含一个stringException ,以定义如何计划将它们映射到实现,但是一切都非常清晰,易于阅读。 我可以从四年后开始阅读你的代码,并且很容易理解发生了什么。

你select哪一个取决于select1和选项2的复杂程度以及它的可扩展性。

所以对于你的具体情况,我会想象你只是从这个exception中拔出一条消息或一些东西:

 public interface IHasMessage { string GetMessage(); } public void test(string a, IHasMessage arg) { //Use message } 

现在,您只需要将一个string和一个Exception转换为IHasMessage的方法。 好简单。

如果ChildClass表示它是从ParentClass派生的,那么可以写下面的内容来接受ParentClass和ChildClass;

 public void test<T>(string a, T arg) where T: ParentClass { //do something } 

另一方面,如果你想使用两个不同的types,而且它们之间没有inheritance关系,你应该考虑实现相同接口的types;

 public interface ICommonInterface { string SomeCommonProperty { get; set; } } public class AA : ICommonInterface { public string SomeCommonProperty { get;set; } } public class BB : ICommonInterface { public string SomeCommonProperty { get; set; } } 

那么你可以写你的通用函数为;

 public void Test<T>(string a, T arg) where T : ICommonInterface { //do something }