C#generics - 我可以从两个选项中选择一个吗?

时间:2010-06-21 15:17:19

标签: c# .net class generics class-design

假设我有以下类层次结构:

Class A {...}

Class B : A  {...}

Class C : A {...}

我目前拥有的是

Class D<T> where T : A {...}

但我想要一些形式

Class D<T> where T in {B,C}

这是由于一些奇怪的行为我不负责B和C有哪些常见的方法不在A中,但是能够在T上用D调用它们会很好。

注意:我无权访问A,B或C进行编辑

7 个答案:

答案 0 :(得分:24)

你需要为B和C中的常用方法定义一个接口(让我们称之为Ibc),让B和C实现这个接口,然后你可以写:

Class D<T> where T : A, Ibc {...}

答案 1 :(得分:9)

这不是直接可能的。

正如其他人所说,您可以定义一个界面并在BC中实施。

如果这不是一个选项(例如,如果这些类超出了您的控制范围),我可能会建议:首先,从一个抽象类开始,该类包含您可以使用任何{{1}实现的所有功能来自T。然后说你有AB的某些方法不属于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

答案 2 :(得分:5)

首先,如果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<T>

答案 3 :(得分:3)

B和C是否实现相同的接口?这可能是一条更好的路线。

答案 4 :(得分:2)

一些选项:

  1. 制作一个包含IderivedFromAB常用方法的界面C
    从您的问题看来这是不可能的
  2. D施放Tdynamic并动态调用方法
    最简单的解决方案,如果您可以使用.Net 4
  3. D测试中,如果您处理的是BC,请投票并致电
    将由编译器检查,并且可以从.Net 2
  4. 进行检查
  5. The Dan Tao answer:为D<T>B创建C的具体实施,这些可以直接从BC调用方法。 (我自己没想过这个) 仅在“用户来源”知道它正在处理BC时才有效,并且不会使用摘要A来使用D<A>。相反,它应该使用DBDC。但我认为情况确实如此,否则你不需要泛型。

答案 5 :(得分:0)

C#中的where约束不允许您指定多个类作为选择。 此外,如果您要指定包含多个where,那么它们都必须满足。约束没有OR逻辑。 以下是规范:http://msdn.microsoft.com/en-us/library/bb384067.aspx

Grzenio的答案似乎适合你。将常见行为提取到B和C的公共接口中。然后,您可以将该接口用作约束。

答案 6 :(得分:0)

由于您无法访问来源,唯一真正的答案(除非您愿意使用dynamic 失去安全感)明确检查B / C和演员。