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

时间:2013-05-20 12:47:41

标签: c# inheritance base-class

我正在读约瑟夫·阿尔巴巴里和本·阿尔巴巴里的书“简而言之的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()
        {
        }
    }
}

2 个答案:

答案 0 :(得分:11)

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

例如,给定:

class Program
{
    static void Main(string[] args)
    {
    }

    internal class A { }
    public class B : A { }
}

编译,因为包装类的internal修饰符使publicB修饰符无法实现。相反,类型B的可访问性受其包装类Program的限制 - 其可访问性域也是internal

如果您将其更新为:

class Program
{
    static void Main(string[] args)
    {
    }
}

internal class A { }
public class B : A { }

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


来自C#规范3.5.2 Accessibility Domains

  

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

     

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

可访问域的MSDN's description

  

如果该成员嵌套在另一个类型中,则为其可访问性域   由成员的可访问性级别和   立即包含类型的可访问性域。

如果换行类型Programinternal,则B的嵌套类型public将具有匹配Program的可访问性,因此会被视为如internal并且不会抛出编译器错误。

答案 1 :(得分:0)

当您通过其他公共类继承私有类时,私有继承类无法在其他类中访问,那么它包含私有类的引用及其数据,因此是不可能的。

abstract class test
    {
        public abstract void add();
        public int num1;
        public string str;
    }
class test3 : test1
    {
        public override void add()
        {
            throw new NotImplementedException();
        }
    }

两个类都是私有的。 如果使用内部,则只能以汇编形式访问。