从非泛型类重写抽象泛型方法

时间:2012-02-08 16:27:30

标签: c# generics override abstract

基类

class Drawer
{
    public abstract void Draw<T>(T type);    
}

派生类#1

class ADrawer : Drawer
{
    public override void Draw<T>(List<T> list)
    {
        foreach (var a in list)
        {
            DrawA(a);
        }
    }

    public void DrawA(Agent a)
    {
        //draw code here
    }
}

派生类#2

class AnotherDrawer : Drawer
{
    public override void Draw<T>(T number)
    {
        if (number == 1)
        {
            //draw code
        }
    }
}

错误发生在#1派生类中:“找不到合适的方法来覆盖”

我应该在基类中使用'virtual'还是'abstract'?

如何设置基本参数类型以允许派生类中的各种参数?

3 个答案:

答案 0 :(得分:8)

您的代码存在的问题多于您提出的问题。暂时不考虑覆盖问题,类ADrawer需要一个类型约束(where T : Agent):

class ADrawer : Drawer 
{ 
    public void Draw<T>(List<T> list) where T : Agent
    { 
        foreach (var a in list) 
        { 
            DrawA(a); 
        } 
    }
    public void DrawA(Agent a) 
    { 
        //draw code here 
    } 
} 

如果没有这种约束,将a传递给DrawA是不合法的,因为aT类型的引用,没有约束就没有隐式转换从类型T到类型Agent

AnotherDrawer类非法使用==运算符。无法将==运算符应用于Tint类型的操作数。您可以使用object.Equals覆盖来解决这个问题。

最后,基类有一个错误,因为它是一个包含抽象成员的非抽象类。

但是,一般情况下,此代码表示应该是通用的,而不是方法

abstract class Drawer<T>
{
    public abstract void Draw(T type);
}

派生类#1

class ADrawer : Drawer<List<Agent>>
{
    public override void Draw(List<Agent> list)
    {
        foreach (var a in list)
        {
            DrawA(a);
        }
    }       

    public void DrawA(Agent a)
    {
        //draw code here
    }
}

派生类#2

class AnotherDrawer : Drawer<int>
{
    public override void Draw(int number)
    {
        if (number == 1)
        {
            //draw code
        }
    }
}

要跟进Eric Lippert的评论,这也是我对你的问题的第一反应,你可能会考虑这个设计:

abstract class Drawer<T>
{
    public abstract void Draw(T type);
    public void DrawMany(IEnumerable<T> types)
    {
        foreach (var t in types)
            Draw(t);
    }
}

派生类#1

class ADrawer : Drawer<Agent>
{
    public override void DrawA(Agent a)
    {
        //draw code here
    }
}

派生类#2没有变化。

答案 1 :(得分:5)

抽象方法应该有这个signeture

  public abstract void Draw<T>(List<T> type);  

答案 2 :(得分:1)

要使其编译,请将基类更改为:

class Drawer
{
    public abstract void Draw<T>(List<T> type);    
}

List<T>T不同,因此当您在派生类'方法中传入List<T>时,您无法覆盖基本方法,因为它具有T 1}}参数,而不是List<T>参数。