C#泛型-我能从两种选择中选择一种吗?
假设我有以下类层次结构:C#泛型-我能从两种选择中选择一种吗?,c#,.net,class,generics,class-design,C#,.net,Class,Generics,Class Design,假设我有以下类层次结构: Class A {...} Class B : A {...} Class C : A {...} 我现在拥有的是 Class D<T> where T : A {...} D类,其中T:A{…} 但我想要这种形式的东西 Class D<T> where T in {B,C} D类,其中T在{B,C} 这是由于一些奇怪的行为,我不负责B和C有不在A中的通用方法,但如果能够在t上的D中调用它们,那就太好了 注意:我无权访问A、B或C
Class A {...}
Class B : A {...}
Class C : A {...}
我现在拥有的是
Class D<T> where T : A {...}
D类,其中T:A{…}
但我想要这种形式的东西
Class D<T> where T in {B,C}
D类,其中T在{B,C}
这是由于一些奇怪的行为,我不负责B和C有不在A中的通用方法,但如果能够在t上的D中调用它们,那就太好了
注意:我无权访问A、B或C来编辑它们B和C实现相同的接口吗?这可能是一个更好的方法。您需要为B和C中的常用方法定义一个接口(我们称之为Ibc),使B和C实现此接口,然后您可以编写:
Class D<T> where T : A, Ibc {...}
D类,其中T:A,Ibc{…}
一些选项:
idedrivedfroma
,其中包含B
和C
中的常用方法从你的问题看来这是不可能的
D
castT
todynamic
中,动态调用方法如果你能使用.NET4,这是最简单的解决方案
D
中,测试您是否处理B
或C
、转换和调用将由编译器检查,并且可以从.Net 2进行检查
B
和C
创建D
的具体实现,它们可以直接从B
和C
调用方法。(我自己没想到这个)。仅当“用户源”知道它处理的是
B
或C
,并且不使用摘要A
来使用D
时,才会起作用。相反,它应该使用DB
或DC
。但我认为是这样的,否则你不需要泛型格泽尼奥的回答似乎适合你。将公共行为提取到B和C的公共接口中。然后可以将该接口用作约束。这不是直接可行的 正如其他人所建议的,您可以定义一个接口并在
B
和C
中实现它
如果这不是一个选项(例如,如果这些类超出了您的控制范围),那么我可能会建议这样做:首先,从一个抽象类开始,该抽象类包含从A
派生的任何t
可以实现的所有功能。然后假设你有一些方法,既适用于B
也适用于C
,它们不是a
的一部分。在D
中,可以通过子类实现这些抽象方法:
public abstract class D<T> where T : A
{
protected T _member;
public void DoSomethingAllTsCanDo()
{
_member.DoSomething();
}
public abstract void DoSomethingOnlyBAndCCanDo();
}
由于您无法访问源代码,唯一真正的答案(除非您愿意使用
动态)是明确检查B
/C
和cast。首先,如果B和C有共同的方法,这是一个设计缺陷,它们不共享接口。也就是说,即使没有访问B和C的权限,您也可以修复此问题。
可以创建一个公共接口。假设你有:
public class A
{
}
public class B : A
{
public void Start() { }
}
public class C : A
{
public void Start() { }
}
您可以创建一个公共接口:
public interface IStartable
{
void Start();
}
并将其用于B和C的派生类:
public class BetterB : B, IStartable
{
}
public class BetterC : C, IStartable
{
}
如果按原样获得B和C实例,则可能无法实现这一点,但如果创建它们,则可以考虑这样做。事实上,对于专门的B和C类,您可以使用接口而不是D
,但是,他不控制源A、B和C。这将使此解决方案有点难以实现。啊,我还没有看到编辑。如果这样的接口不存在,那么就我所知,没有直接的方法来实现D类。+1-这是首选的解决方案。我补充了一个答案,说明在某些情况下如何做到这一点。很奇怪你得到了公认的答案@Jean Bernard Pellerin-你能解释一下你是如何解决的吗?事实上,最后我没有使用你的任何一个答案。我给一个被真实方法覆盖的扩展方法添加了一个:)我喜欢这个答案。它还提供了一个更通用的解决方案,其中没有a,例如,如果B和C来自具有不同来源的库
public class BetterB : B, IStartable
{
}
public class BetterC : C, IStartable
{
}