简体   繁体   English

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

[英]When using generic types, how can I call an method from an inherited class instead of a base class?

I have a base class which implemnts DependsOn() 我有一个实现DependsOn()的基类

public class Entity
{
    protected Entity() { }

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

I've extended this base class. 我已经扩展了这个基类。

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

I would expect the following code to return "new List {typeof(Scenario)}", instead it returns a empty list (its calling the DependsOn method from the base class, instead of the inherited class. I verified this with a debugger as well.) 我希望以下代码返回“新列表{typeof(Scenario)}”,而不是返回一个空列表(它从基类而不是继承的类调用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);

Use override instead of virtual new . 使用override而不是virtual new

virtual new creates a new slot and defines a new function that is itself virtual but doesn't share the vtable slot with its base class. virtual new创建一个新插槽,并定义一个新的函数,该函数本身是virtual但不与其基类共享vtable插槽。

Every time you use the new keyword on a function, you should think of it as being unrelated to the function with the same name in the base class. 每次在函数上使用new关键字时,都应认为它与基类中具有相同名称的函数无关。 new allows you to completely change the signature of the function for instance. new允许您例如完全更改函数的签名。

You haven't really extended the base class, you created a new method with the same name. 您尚未真正扩展基类,而是创建了一个具有相同名称的新方法。 Use the override keyword as follows: 使用override关键字,如下所示:

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

Why you need override in this case instead of new is, the method is called from the base class object which contains child class at runtime. 在这种情况下,为什么需要覆盖而不是新方法,是在运行时从包含子类的基类对象调用该方法的。 Actual passed element is of type Entity type, which gets filled up with waveform at runtime, but at runtime, Entity object is not aware of any override, since the child class implementation is hiding base class implementation. 实际传递的元素是实体类型,在运行时会被波形填充,但是在运行时,实体对象不知道任何替代,因为子类实现隐藏了基类实现。

In original format only way to call the correct method that you want is by using the Waveform object, instead of entity, it will then call the correct version, as shown below: 在原始格式下,调用所需的正确方法的唯一方法是使用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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM