C# 从泛型中继承 class 作为类型

C# inherited class from generic as a type

我对泛型有疑问。我有那些 classes :

abstract class BaseTestClass<T> : where T : class, new()
{
   //base test class implementation
   public abstract void Run(BaseDataClass<T> data);
}

class BaseDataClass<T> : where T : class, new()
{
   //base data class implementation
}

class DataA : BaseDataClass<SettingsA>
{
   //some stuff
}

class TestA : BaseTestClass<SettingsA>
{
   //Works!
   public override void Run(BaseDataClass<SettingsA> data)
   {
   }
   //Doesn't Work!
   public override void Run(DataA data)
   {
   }

}

我的问题是为什么我不能在抽象方法中使用继承的class?

[编辑] 编译时的错误是:

TestA does not implement inherited abstract member Run(BaseDataClass)

它不起作用,因为您不能用两种方法覆盖一种方法。取消对 TestA 中的一种方法的覆盖,它将全部起作用。无论如何,在单个 class.

中两次覆盖单个方法是没有意义的

可以,但是 BaseTestClass<SettingsA> 基础 class 根本没有覆盖签名 Run(DataA) 的方法,只有签名 Run(BaseDataClass<DataA>) 之一。

泛型继承也就是泛型T类型相同

你的第二个方法没有编译,因为没有方法可以被它覆盖,删除 override 修饰符将使你的代码编译。

如果你想有一个方法运行只在参数为DataA类型时,但仍然执行接口方法实现,你可以这样做:

class TestA : BaseTestClass<SettingsA>
{
   //Works!
   public override void Run(BaseDataClass<SettingsA> data)
   {
   }

   public void Run(DataA data)
   {
       //dp some stuff
       Run((BaseDataClass<SettingsA>)data);
   }

}

但请注意,这不是防弹的,您可能会错过盒装电话,更好的方法是这样做:

class TestA : BaseTestClass<SettingsA>
{
   //Works!
   public override void Run(BaseDataClass<SettingsA> data)
   {
        var myDataA = data as DataA;
        if (myDataA != null)
        {
            //your parameter is a DataA;
        }
   }
}

您可以使用额外的泛型参数、类型安全且不强制转换来实现此功能:

internal abstract class BaseTestClass<T, Y>
    where T : class, new()
    where Y : BaseDataClass<T>
{
    private T m_data;

    //base test class implementation
    public abstract void Run(Y data);
}

public class BaseDataClass<T> where T : class, new()
{
}


internal class TestA : BaseTestClass<SettingsA, DataA>
{
    public override void Run(DataA data)
    {
        throw new NotImplementedException();
    }
}

class DataA : BaseDataClass<SettingsA>
{    
}

class SettingsA
{
}

这是类型安全的,因为约束是

where Y : BaseDataClass<T>

如果你不需要直接在你的基础class中使用T,你可以只使用一个通用参数并删除T