派生类使用了错误的方法
本文关键字:错误 方法 派生 | 更新日期: 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节)。(重点矿井)