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

Jea*_*rin 22 .net c# generics class-design class

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

Class A {...}

Class B : A  {...}

Class C : A {...}
Run Code Online (Sandbox Code Playgroud)

我现在拥有的是

Class D<T> where T : A {...}
Run Code Online (Sandbox Code Playgroud)

但我想要一些形式

Class D<T> where T in {B,C}
Run Code Online (Sandbox Code Playgroud)

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

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

Grz*_*nio 24

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

Class D<T> where T : A, Ibc {...}
Run Code Online (Sandbox Code Playgroud)

  • 但是,他不控制源A,B和C.这将使这个解决方案难以实现. (7认同)
  • 实际上最后我没有使用你的任何一个答案。我向 A 添加了一个扩展方法,该方法被真实的方法覆盖了:) (2认同)

Dan*_*Tao 9

这不是直接可能的.

正如其他建议,你可以定义一个接口,并都实现它BC.

如果这不是一个选项(例如,如果这些类超出了您的控制范围),我可能建议的是:首先,从一个抽象类开始,该类包含您可以通过任何T派生实现的所有功能A.然后说你有存在两种一些方法BC不在的一部分A.在D您可以使这些抽象方法由子类实现:

public abstract class D<T> where T : A
{
    protected T _member;

    public void DoSomethingAllTsCanDo()
    {
        _member.DoSomething();
    }

    public abstract void DoSomethingOnlyBAndCCanDo();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以从每个类型的基类继承B,C并覆盖抽象方法以提供适当的功能:

public class DB : D<B>
{
    public override void DoSomethingOnlyBAndCCanDo()
    {
        _member.DoSomethingOnlyBCanDo();
    }
}

public class DC : D<C>
{
    public override void DoSomethingOnlyBAndCCanDo()
    {
        _member.DoSomethingOnlyCCanDo();
    }
}
Run Code Online (Sandbox Code Playgroud)


Kob*_*obi 5

首先,如果B和C有共同的方法,那么它们不共享接口是一个设计缺陷.也就是说,即使没有访问B和C,您也可以解决这个问题.
可以创建一个通用接口.假设你有:

public class A
{
}
public class B : A
{
    public void Start() { }
}
public class C : A
{
    public void Start() { }
}
Run Code Online (Sandbox Code Playgroud)

您可以创建一个通用界面:

public interface IStartable
{
    void Start();
}
Run Code Online (Sandbox Code Playgroud)

并在B和C的派生类中使用它:

public class BetterB : B, IStartable
{
}
public class BetterC : C, IStartable
{
}
Run Code Online (Sandbox Code Playgroud)

如果按原样获得B和C实例,则可能无法实现,但可以考虑创建它们.实际上,对于B和C的专用类,您可以使用接口而不是D<T>.