使用继承的参数化继承泛型

use*_*261 6 c# generics inheritance

我正在寻找一种方法来继承遗传参数化的泛型 - 或者如果不可能,那么最接近获得相同功能的方法.

考虑以下:

B类继承自A类

D类继承自C类

现在,我有一节课:

abstract class A<T> where T : C
Run Code Online (Sandbox Code Playgroud)

与构造函数:

public A(T t)
Run Code Online (Sandbox Code Playgroud)

现在,我希望将A类扩展为:

class B<D> : A<C>
Run Code Online (Sandbox Code Playgroud)

创建构造函数:

 public B(D t) : base(t){ /*stuff here*/}
Run Code Online (Sandbox Code Playgroud)

但是,这会引发编译时错误,因为D不是C.所以我的两个问题是:

a)有干净的方法吗?在最糟糕的情况下,我认为我可以用C代替D而没有什么问题,但也许这就是为什么这不是一个安全的想法?

b)我是否应该在子类定义中明确说明我的泛型,或者是否有更简洁的方法我应该使用约束类型?

Tyr*_*son 2

向 B 类添加 where 约束

class B<D> : A<C> where D : C
Run Code Online (Sandbox Code Playgroud)

回答您的问题:

a)通过此答案中的修复,到目前为止,您的方法非常干净,如果有点过于抽象(主要是由于名称)。

b) 仅当子类本身以与作为 D 实例的 C 子类相关的通用方式添加值时,才应将 D 泛型类型参数添加到子类 B;或者如果子类本身不完整,需要扩展并且需要知识 C 的子类作为 D。在这种情况下,您应该将其标记为抽象。

更新

我还想补充一件事。在上面的签名中,A 中使用该类型的成员中T的参数将是 C。这可能是一个问题,如以下示例所示:A<T>T

public class C {}

public class F : C {}

public class E : C {}

public class A<T> where T : C
{
    protected T cSubclass;
    public void SetCSubclass(T cSubclass) { this.cSubclass = cSubclass; }
}

public class B<D> : A<C> where D : C
{
    public D GetCSubclass()
    {
        return this.cSubclass;
    }
}
Run Code Online (Sandbox Code Playgroud)

此示例中的代码将无法编译。您将收到以下编译错误:

error CS0266: Cannot implicitly convert type 'C' to 'D'. An explicit conversion exists (are you missing a cast?)
Run Code Online (Sandbox Code Playgroud)

但是,如果我们将 B 类更改为以下内容,编译错误就会得到解决:

public class B<D> : A<D> where D : C
{
    public D GetCSubclass()
    {
        return this.cSubclass;
    }
}
Run Code Online (Sandbox Code Playgroud)

原因是 D 是 C 的特定子类,但是在之前的版本中,我们仅将 A 限制为 C 的任何形式,包括其自身及其任何子类。因此,我们可能会调用new B<F>.SetCSubclass(new E());与 GetCSubclass 期望返回的类型不同的类型。在后一个版本中,我们将 D 指定为在 A 中使用的类型参数,强制B<F>.SetCSubclass仅接受 的实例F

这提供了使用此类模式的开发人员可能期望的更高程度的类型安全性。