派生类使用了错误的方法

本文关键字:错误 方法 派生 | 更新日期: 2023-09-27 18:29:12

我已经将代码简化为这个

 internal class Program
{
    private static void Main(string[] args)
    {
        Child d = new Child();
        int i = 100;
        d.AddToTotal(i);
        Console.ReadKey();
    }
    private class Parent
    {
        public virtual void AddToTotal(int x)
        {
            Console.WriteLine("Parent.AddToTotal(int)");
        }
    }
    private class Child : Parent
    {
        public override void AddToTotal(int number)
        {
            Console.WriteLine("Child.AddToTotal(int)");
        }
        public void AddToTotal(double currency)
        {
            Console.WriteLine("Child.AddToTotal(double)");
        }
    }
}

问题是这称为

public void AddToTotal(double currency)

尽管我用int调用它,它应该使用

public override void AddToTotal(int number)

使用父级返回预期结果。

 Parent d = new Child();
 int i = 100;
 d.AddToTotal(i);

更新:

感谢@Jan和@azybrezovsky向我介绍了规范。我已经在基类中添加了一个虚拟的空方法来暂时解决这个问题。

派生类使用了错误的方法

类型T中名称N的成员查找处理如下:

首先,构造了在T中声明的名为N的所有可访问成员的集合和T的基类型包含覆盖修饰符的声明被从集合中排除如果没有名为N的成员存在并且可以访问,则查找不会产生匹配,并且不会评估以下步骤。

因此,当您使用子类型的变量时

Child d = new Child();
int i = 100;
d.AddToTotal(i);

方法public override void AddToTotal(int number)被从集合中排除,并且我们只剩下一个名称为N的方法。Int被隐式转换为double,因此没有发生错误。

这个问题的答案解释了发生这种情况的技术原因。为了方便起见,我在这里包含了答案,但所有的功劳都归功于tvanfosson。

请参阅C#语言规范中关于成员查找的部分和过载解决方案。派生类的重写方法由于成员查找和基础的规则,不是候选类方法不是基于重载解决方案的最佳匹配规则。

第7.3节

首先,名为N的所有可访问成员的集合(第3.5节)在T中声明,并且构造T的基类型(第7.3.1节)。包含重写修饰符的声明被排除在设置如果没有名为N的成员存在并且可以访问,则查找不产生匹配,并且不评估以下步骤。

第7.4.2节:

这些上下文中的每一个都定义了一组候选功能成员以及参数列表,如中所述请参阅上面列出的部分中的详细信息。例如方法调用的候选不包括标记的方法重写(第7.3节),基类中的方法不是候选者如果派生类中的任何方法适用(第7.5.5.1节)。(重点矿井)