这个C#代码合法吗?

Dan*_*mov 4 .net c# mono c#-5.0 methodaccessexception

我已A.Test()声明public virtualB.Test()声明为private new.
我是base.Test()C那个继承人那里打来的B.

此代码使用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 ();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我得到的例外:

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

这是正确的行为吗?

这是在Microsoft .NET中编译还是使用较新版本的Mono编译?
C#规范对此有何看法?
它是否随C#版本而变化?

Jon*_*eet 12

它是有效的C#,但Mono 2.10.2编译器显然做错了.使用MS编译器,调用将base.Test()编译为:

IL_0008:  ldarg.0
IL_0009:  call       instance void A::Test()
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,Derived中的F声明隐藏了从Base继承的F,但由于Derived中的新F具有私有访问权限,因此其范围不会扩展到MoreDerived.因此,MoreDerived.G中的调用F()是有效的并将调用Base.F.

我强烈怀疑Mono 2.10.2盲目地插入一个调用B.Test()- 不是因为它看到了私有方法的存在,而只是为了确保"调用基类方法".碰巧的是,这在执行时非常糟糕.选择调用哪个基类方法是一个有趣的方法,B 可以在C的编译时和执行时间之间进行更改,以覆盖Test()...此时行为是不明显的.Eric Lippert在一篇你可能感兴趣的博客文章中谈到这一点.