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

时间:2015-03-30 14:26:22

标签: c# generics inheritance

我遇到了泛型问题。我是那些课程:

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)
   {
   }

}

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

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

  

TestA不实现继承的抽象成员Run(BaseDataClass)

4 个答案:

答案 0 :(得分:5)

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

通用继承也意味着通用T类型是相同的。

答案 1 :(得分:2)

您可以使用额外的通用参数Type-Safe和不使用强制转换来实现此目的:

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>

如果您不直接在基类中使用T,则只能使用一个通用参数并删除T

答案 2 :(得分:1)

它不起作用,因为你不能用两种方法覆盖一个方法。从TestA中的一个方法中删除它,它将全部起作用。无论如何,在单个班级内两次覆盖单个方法毫无意义。

答案 3 :(得分:1)

你的第二个方法没有编译,因为没有方法可以被它覆盖,删除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;
        }
   }
}