如何用重载和重写方法解释这种行为



谁能这么好,解释一下为什么这个代码显示Derived.DoWork(double)。我可以想出一些解释这种行为,但我希望有人为我澄清这一点。

using System;
public class Base
{
    public virtual void DoWork(int param) {
        Console.WriteLine("Base.DoWork");
    }
}
public class Derived : Base
{
    public override void DoWork(int param) {
        Console.WriteLine("Derived.DoWork(int)");
    }
    public void DoWork(double param) {
        Console.WriteLine("Derived.DoWork(double)");
    }
    public static void Main() {
        int val = 5;
        Derived d = new Derived();
        d.DoWork(val);
    }
}

Eric lippert过去常说"越近越好"。

首先在派生类中声明的方法比首先在基类中声明的方法更接近。

所以从上面的链接来看,派生类更接近,因此选择了派生类。

这个行为被小心地实现以避免脆弱的基类问题

为了完整起见,我将分享这些符号:

  • 首先在派生类中声明的方法比首先在基类中声明的方法更接近。

  • 嵌套类中的方法比包含类中的方法更接近。

  • 任何接收类型的方法都比任何扩展方法更接近。

  • 在嵌套命名空间中的类中找到的扩展方法比在外部命名空间中的类中找到的扩展方法更接近。

  • 在当前命名空间中的类中找到的扩展方法比在using指令中提到的命名空间中的类中找到的扩展方法更接近。

  • 在using指令中提到的命名空间中的类中找到的扩展方法,如果该指令位于嵌套的命名空间中,则比在using指令中提到的命名空间中的类中找到的扩展方法更接近。

此行为在c#语言规范中定义,特别是第7.5.3节"重载解析"。这里是一个旧版本的链接,否则请参考CSharp语言规范。docx,您应该在本地拥有,例如,C:Program Files (x86)Microsoft Visual Studio 12.0VC#Specifications1033CSharp语言规范。docx.

在这种情况下,标记为override的方法被排除在外,因此double过载是唯一有效的选项(强调我的):

每个上下文都定义了候选函数成员的集合参数列表有自己独特的方式,如详细信息请参见上面列出的部分。例如,的集合方法调用的候选对象不包括标记的方法override(§7.4)和基类中的方法都不是候选对象(如果有的话)方法在派生类中是适用的(§7.6.5.1)。

这个行为显然是被设计出来的:

'当选择重载时,如果在派生类中声明了任何兼容的方法,则在基类中声明的所有签名都将被忽略-即使它们在同一个派生类中被重写!'http://social.msdn.microsoft.com/Forums/vstudio/en-US/a70b25d4-f310-4d06-9dc2-a453f822f4f3/function-not-getting-called-when-overloading-the-function-of-base-class-in-derived-class-with?forum=csharpgeneral

最新更新