重载继承类中的方法

Yar*_*lav 14 .net c# clr

我已经开始明白,我不明白发生了什么.C#中存在以下行为:

public class Base
{
    public void Method(D a)
    {
        Console.WriteLine("public void Method(D a)");
    }
}

public class Derived: Base
{
    public void Method(B a)
    {
        Console.WriteLine("public void Method(B a)");
    }
}

public class B { }

public class D: B { }

class Program
{
    static void Main(string[] args)
    {
        Derived derived = new Derived();
        D d = new D();

        derived.Method(d);
    }
}
Run Code Online (Sandbox Code Playgroud)

它会打印出来

public void Method(B a)

代替

public void Method(D a)

这令人惊讶.我想这种行为的原因是方法表的实现.如果CLR在当前类型中找到相应的方法,则它不会搜索基类中的方法.我认为他们正在努力提高绩效.

但我对以下代码完全失望:

public class Base
{
    public virtual void Method(D a)
    {
        Console.WriteLine("public void Method(D a)");
    }
}

public class Derived: Base
{
    public override void Method(D a)
    {
        Console.WriteLine("public override void Method(D a)");
    }

    public void Method(B a)
    {
        Console.WriteLine("public void Method(B a)");
    }

}

public class B { }

public class D: B { }

class Program
{
    static void Main(string[] args)
    {
        Derived derived = new Derived();
        D d = new D();

        derived.Method(d);
    }
}
Run Code Online (Sandbox Code Playgroud)

它会打印出来

public void Method(B a)

代替

public override void Method(D a)

这太糟糕了,非常不可预测.

有人能解释一下吗?

我想方法表只有在当前类型中实现的方法(不包括重写方法),并且只要找到任何可以调用的方法,CLR就会停止查找相应的方法.我对吗?

Eri*_*ert 15

我已经开始明白,我不明白发生了什么.

从而开始智慧.

这太糟糕了,非常不可预测.

它既不是.相比之下,该功能旨在通过消除脆性基类故障的原因减少不可预测性.

有人能解释一下吗?

请参阅我2007年关于此主题的文章.

https://blogs.msdn.microsoft.com/ericlippert/2007/09/04/future-breaking-changes-part-three/

简短的版本是:派生类中的方法总是比基类中的方法更好; 编写派生类的人更多地了解对象语义,并且处理比编写基类的人更具体的情况.

Servy指出我没有报道你的第二点.为什么派生类中的覆盖不会使"D"方法"在派生类中"?

虚方法被认为是声明它们的类的方法,而不是它们最近被覆盖的类的方法.为什么?因为选择是否覆盖是类的实现细节,而不是公共表面区域的一部分.

我想说的是,考虑一下.你写了一些代码,它可以工作,然后你说,嘿,我将在这个类型层次结构的某个地方创建一个新的(或删除旧的!)覆盖此方法,并突然在其他地方更改重载决策?这正是C#试图消除的那种脆弱性.

请记住,C#经过精心设计,适用于人员编辑代码的世界.奇怪的是,许多现代语言被设计成好像一个人正在编写所有代码并且他们第一次就做对了; 那是不现实的.C#的一些更不寻常的功能,就像你发现的一样,可以帮助你保持程序行为的可预测性,即使其他人正在编辑你的基类.