为什么忽略基类中声明的签名?

时间:2010-09-05 22:24:03

标签: c# inheritance

class Base
{
    public virtual void MethodA(int x)
    {
        Console.WriteLine ("In Base Class");
    }
}

class Derived : Base
{
    public override void MethodA(int x)
    {
        Console.WriteLine ("In derived INT)");
    }

    public void MethodA(object o)
    {
        Console.WriteLine ("In derived OBJECT");
    }
}

class Test
{
    static void Main()
    {
        Derived d = new Derived();
        int k = 20;
        d.MethodA(k);
    }
}

我得到的输出是“在派生的OBJECT ”。这种奇怪行为的原因是什么?经过一些研究,我发现原因是基类中声明的签名被忽略。他们为什么被忽视?

2 个答案:

答案 0 :(得分:6)

这是设计上有充分理由的。此设计有助于防止脆弱的基类问题。 C#旨在使编写“版本化”组件变得更容易和更安全,而这一规则是其中很重要的一部分。

这是一个非常常见的问题。这是我们得到的最常见的“错误报告”之一;也就是说,有人认为他们在编译器中发现了一个错误,实际上他们找到了一个功能。

有关该功能的说明及其设计原因,请参阅我关于此主题的文章:

http://blogs.msdn.com/b/ericlippert/archive/2007/09/04/future-breaking-changes-part-three.aspx

有关各种语言如何处理脆弱基类问题的更多文章,请参阅我关于该主题的文章存档:

http://blogs.msdn.com/b/ericlippert/archive/tags/brittle+base+classes/

答案 1 :(得分:2)

VC#2008中的编译器在确定要调用的内容时检查虚拟函数之前的可用非虚函数。由于Derived类具有可以调用的非虚拟MethodA(对象),因此编译器会调用它。

如果向Base添加虚拟MethodA(对象),则会调用Derived.MethodA(int),因为MethodA(object)和MethodA(int)都是虚拟的。

我对C#语言规范不太熟悉,不知道这是指定的行为,还是编译器中的错误。