这个c#代码合法吗?



我将A.Test()声明为public virtual, B.Test()声明为private new
我从继承BC调用base.Test()

这段代码可以在Mono 2.10.2下编译,但是会抛出MethodAccessException:

class A {
    public virtual void Test () { }
}
class B : A {
    private new void Test () { }
}
class C : B {
    public C ()
    {
        base.Test ();
    }
    public static void Main (string[] args)
    {
        var c = new C ();
    }
}

下面是我得到的例外:

System.MethodAccessException: Method TestBug.B:Test () is inaccessible from method TestBug.C:.ctor ()

这是正确的行为吗?

这在microsoft.net或新版本的Mono中编译吗?
c#规范对此有何规定?
它是否随c#版本而变化?

这是有效的c#,但Mono 2.10.2编译器显然是做错误的事情。使用MS编译器,对base.Test()的调用被编译为:

IL_0008:  ldarg.0
IL_0009:  call       instance void A::Test()

Mono 3.0.6.0编译器的工作方式相同。

A而言,B.Test()实际上是不存在的。

事实上,c# 5规范的3.7节甚至给出了一个显式的示例,与您的示例非常相似:

新成员的声明只在新成员的作用域中隐藏继承的成员。

class Base
{
    public static void F() {}
}
class Derived: Base
{
    new private static void F() {}   // Hides Base.F in Derived only
}
class MoreDerived: Derived
{
    static void G() { F(); }         // Invokes Base.F
}

在上面的例子中,Derived中的F的声明隐藏了从Base继承的F,但是由于Derived中的新F具有私有访问,因此它的作用域不会扩展到MoreDerived。因此,调用MoreDerived中的F()。G是有效的,并且将调用Base.F.

我强烈怀疑Mono 2.10.2盲目地插入了对B.Test()的调用——不是因为它看到了私有方法的存在,而只是为了确保调用了基类方法。碰巧的是,这在执行时很糟糕。关于调用哪个基类方法的选择是一个有趣的选择,因为B 可以在C的编译时间和执行时间之间改变,以覆盖Test()…在这一点上,行为是不明显的。Eric Lippert在一篇博客文章中谈到了这一点,你可能会觉得很有趣。

相关内容

  • 没有找到相关文章

最新更新