0

为什么私有类子类的用户不能访问私有类的公共成员数据?以下对我来说似乎非常违反直觉,因为它不会编译:

public class OuterClassBase {
    private class PrivateInnerClass {
        public void DoSomething () {}
    }

    protected class ProtectedInnerClass : PrivateInnerClass {}
}


public class OuterClassDerived : OuterClassBase {
    public OuterClassDerived () {
        ProtectedInnerClass o = new ProtectedInnerClass();
        o.DoSomething(); // inaccessible due to its pretection level
    }
}

公开PrivateInnerClass/受保护允许代码编译...

4

3 回答 3

3

从 C# 4 规范的第 3.5 节:

成员声明允许控制成员访问。成员的可访问性由成员声明的可访问性(第 3.5.1 节)与直接包含类型(如果有)的可访问性相结合来建立。
...
当访问发生的文本位置包含在成员的可访问域(第 3.5.2 节)中时,允许访问成员。

然后在第 3.5.2 节(可访问域)中:

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

  • 如果 M 声明的可访问性是公共的,则 M 的可访问域是 T 的可访问域。
  • ...
  • 如果 M 声明的可访问性是私有的,则 M 的可访问域是 T 的程序文本。

这里就是这种情况。所以可访问域DoSomethingPrivateInnerClass第一个项目符号的可访问域......但可访问域PrivateInnerClass是最后一个项目符号的程序文本OuterClassBase

因此调用 inside不在OuterClassDerived的可访问域中,所以它不能调用它。DoSomething

我真的很惊讶你能从一开始就派生ProtectedInnerClassPrivateInnerClass...

编辑:事实证明你不能......即使OuterClassDerived完全删除了这个类,你也会收到这个错误:

Test.cs(10,21): error CS0060: Inconsistent accessibility: base class
        'OuterClassBase.PrivateInnerClass' is less accessible than class
        'OuterClassBase.ProtectedInnerClass'

这违反了规范的第 10.1.4.1 节:

类类型的直接基类必须至少与类类型本身一样可访问(第 3.5.2 节)。例如,公共类从私有或内部类派生是编译时错误。

在这里,您尝试从私有类派生受保护类 - 受保护类比私有类更容易访问,因此会出现错误。

于 2012-07-20T21:12:26.220 回答
2

PrivateInnerClass 对 OuterClassBase 是私有的——除了 OuterClassBase 没有人可以使用它(这就是私有的意思)。

子类化它不会改变规则,它仍然是私有的——如果子类化将打破私有约束并允许 OuterBaseClass 之外的人访问 PrivateInnerClass 的成员,那么这是非法的并且不会编译。

换句话说,如果某些东西被声明为私有而不是私有,那么任何允许您绕过私有声明的技巧都不应该编译(反射除外)。

于 2012-07-20T20:56:31.323 回答
0

受保护的类不能从私有类继承,原因与公共类不能从内部类继承的原因相同:一个类不能比它的基类更容易访问。

但是你为什么要这样做呢?您可以阻止其他类直接从 PrivateInnerClass 继承,但前提是它们位于不同的程序集中。你也可以做这样的事情;该框架对内部/公共类做了很多工作:

public class OuterClassBase
{
    private class PrivateInnerClass : ProtectedInnerClass
    {
    }

    protected abstract class ProtectedInnerClass
    {
        public void DoSomething() { }
    }

    protected ProtectedInnerClass ProtectedInnerClassFactoryMethod()
    {
        return new PrivateInnerClass();
    }
}

public class OuterClassDerived : OuterClassBase
{
    public OuterClassDerived()
    {
        ProtectedInnerClass o = ProtectedInnerClassFactoryMethod();
        o.DoSomething();
    }
} 
于 2012-07-20T21:32:03.443 回答