使用泛型类型时,如何从继承的类而不是基类调用方法?

时间:2014-09-28 00:51:52

标签: c# inheritance generic-type-argument

我有一个实现DependsOn()

的基类
public class Entity
{
    protected Entity() { }

    public virtual List<Type> DependsOn()
    {
        return new List<Type>();
    }
}

我扩展了这个基类。

public class Waveform : Entity
{
    public virtual new List<Type> DependsOn()
    {
        return new List<Type> {typeof(Scenario)};
    }
}

我希望以下代码返回&#34; new List {typeof(Scenario)}&#34;而是返回一个空列表(它从基类调用DependsOn方法,而不是继承类我也用调试器验证了这一点。)

public virtual List<Entity> FindParents<T>(T possibleChild) where T : Entity
{
    List<Type> dependsOnTypes = possibleChild.DependsOn();
}

public void DeleteEntity<T>(T entity) where T : Entity
{
    List<Entity> parents = FindParents<T>(entity);
}

Waveform waveform = new Waveform();
DeleteEntity<Waveform>(waveform);

3 个答案:

答案 0 :(得分:4)

使用override代替virtual new

virtual new创建一个新的插槽并定义一个 new 函数,该函数本身为virtual但不与其基础共享vtable插槽类。

每次在函数上使用new关键字时,都应该将其视为与基类中具有相同名称的函数无关。 new允许您完全更改函数的签名。

答案 1 :(得分:2)

您还没有真正扩展基类,您创建了一个具有相同名称的新方法。使用override关键字,如下所示:

public class Waveform : Entity
{
    public override List<Type> DependsOn()
    {
        return new List<Type> {typeof(Scenario)};
    }
}

答案 2 :(得分:1)

为什么在这种情况下需要覆盖而不是new,该方法是从运行时包含子类的基类对象调用的。实际传递的元素是实体类型,在运行时会被波形填充,但在运行时,实体对象不知道任何覆盖,因为子类实现隐藏了基类实现。

原始格式只调用所需的正确方法是使用Waveform对象而不是实体,然后调用正确的版本,如下所示:

 class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            Waveform waveform = new Waveform();
            p.DeleteEntity<Waveform>(waveform);
        }

        public void DeleteEntity<T>(T entity) where T : Waveform
        {
            List<Entity> parents = FindParents<T>(entity);
        }

        public virtual List<Entity> FindParents<T>(T possibleChild) where T : Waveform
        {
            List<Entity> dependsOnTypes = possibleChild.DependsOn();
            return dependsOnTypes;
        }        
    }

    public class Entity
    {
        protected Entity() { }

        public virtual List<Entity> DependsOn()
        {
            return new List<Entity>();
        }
    }

    public class Waveform : Entity
    {
        public virtual new List<Entity> DependsOn()
        {
            return new List<Entity> { new Scenario() };           
        }
    }

    public class Scenario: Entity
    {
        int x;
        float y;
    }