overriding abstract generic method from non generi

2019-06-22 12:15发布

base class

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

derived class #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
    }
}

derived class #2

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

The error is in the #1 derived class : "no suitable method found to override"

Should I be using 'virtual' in the base class as well as 'abstract' ?

How should I set the base parameter type to allow a variety of parameters in derived classes?

3条回答
倾城 Initia
2楼-- · 2019-06-22 12:45

abstract method should have this signeture

  public abstract void Draw<T>(List<T> type);  
查看更多
Summer. ? 凉城
3楼-- · 2019-06-22 12:46

To get it to compile change the base class to this:

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

List<T> is not the same as T, so when you pass in a List<T> in the derived class' method you can't override the base method as that has a T parameter, not a List<T> parameter.

查看更多
倾城 Initia
4楼-- · 2019-06-22 12:54

Your code has more problems than just the one you ask about. Setting aside the override question for the moment, class ADrawer needs a type constraint (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 
    } 
} 

Without that constraint, it's not legal to pass a to DrawA, because a is a reference of type T, and without the constraint there is no implicit conversion from type T to type Agent.

The AnotherDrawer class has an illegal use of the == operator. It's not possible to apply the == operator to operands of type T and int. You could get around that by using the object.Equals override.

Finally, the base class has an error because it is a non-abstract class containing an abstract member.

In general, however, this code indicates that the class should be generic, rather than the method:

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

derived class #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
    }
}

derived class #2

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

To follow up on Eric Lippert's comment, which was also my first reaction to your question, you might consider this design instead:

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

derived class #1

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

Derived class #2 is unchanged.

查看更多
登录 后发表回答