可访问性不一致:基类比子类更难访问

我正在读约瑟夫阿尔巴巴里和本阿尔巴巴里的书“简而言之的C#4.0”。 从那里我发现访问修饰符的主题限制。 第91页,主题“访问修饰符的限制”。

从书中引用。

编译器可防止任何不一致的访问修饰符的使用。 例如,子类本身可以比基类更难访问,但不能更多

所以这说明基类应该与子类相同或更易于访问。 因此,如果基类是内部的,那么子类应该是私有的或内部的。 如果基类是私有的,而子类是公共的,那么将生成编译时错误。 在Visual Studio中尝试此操作时,我发现了一些奇怪的行为。

尝试1:Base是私有的,子类是私有的(Works,正确的行为)如果两者都是内部的,那么它也有效。

private class A { } private class B : A { } // Works 

尝试2:Base是私有的,子类是public或internal(这是失败的,正确的行为)

 private class A { } public class B : A { } // Error 

尝试3:Base是内部的,sub是公共的(这是有效的,但它应该失败。因为Base比子类更难访问

 internal class A { } public class B : A { } // Works, but why 

现在我的问题是为什么试试3没有失败? 子类是公共的,比内部的基类更容易访问。 即使这本书说这应该失败。 但Visual Studio成功编译了这个。 这应该工作与否?

编辑:

我在VS中创建了一个新的控制台项目。 在Program.cs中,我添加了我的代码。 这是Program.cs文件的完整代码。

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace ConsoleApplication { class Program { internal class A { } public class B : A { } // Error static void Main() { } } } 

您将嵌套类放在另一个internal类中。

例如,给定:

 class Program { static void Main(string[] args) { } internal class A { } public class B : A { } } 

它将编译,因为包装类的internal修饰符使得类B上的public修饰符没有实际意义。 相反,类型B的可访问性受其包装类Program限制 – 其可访问性域也是internal

如果您将其更新为:

 class Program { static void Main(string[] args) { } } internal class A { } public class B : A { } 

它会抛出不一致的可见性编译器错误。 或者,如果您将Program重新定义为public而不是internal它也会抛出错误。 在这种情况下, B的可访问域现在是public ,不再受Programinternal可访问域限制。


来自C#规范3.5.2可访问域 :

在程序P中的类型T中声明的嵌套成员M的可访问域定义如下(注意M本身可能是类型):

如果M的声明可访问性是公共的,则M的可访问域是T的可访问域。

以及MSDN对可访问域的描述 :

如果成员嵌套在另一个类型中,则其可访问性域由成员的可访问性级别和直接包含类型的可访问性域确定。

如果包装类型Programinternal ,那么嵌套类型Bpublic将具有匹配Program可访问性,因此它被视为internal并且不会引发编译器错误。