C#继承私有类和不访问公共成员

时间:2012-07-20 20:48:37

标签: c# inheritance

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

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 public / protected允许代码编译......

3 个答案:

答案 0 :(得分:3)

来自C#4规范的第3.5节:

  

成员声明允许控制成员访问。成员的可访问性由成员的已声明的可访问性(第3.5.1节)以及直接包含类型的可访问性(如果有)确定。   ...
  当访问发生的文本位置包含在成员的可访问性域(第3.5.2节)中时,允许访问成员。

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

  

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

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

这就是这种情况。因此,DoSomething的辅助功能域是第一个项目符号PrivateInnerClass的辅助功能域...但PrivateInnerClass的辅助功能域是最终OuterClassBase的程序文本子弹。

因此OuterClassDerived中的DoSomething内的呼叫在ProtectedInnerClass的辅助功能域中,因此无法呼叫它。

我真的很惊讶你可以从PrivateInnerClass首先获得OuterClassDerived ......

编辑:事实证明你不能......甚至完全删除Test.cs(10,21): error CS0060: Inconsistent accessibility: base class 'OuterClassBase.PrivateInnerClass' is less accessible than class 'OuterClassBase.ProtectedInnerClass' 课程,你会收到这个错误:

{{1}}

这违反了规范的第10.1.4.1节:

  

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

这里你试图从私有类派生一个受保护的类 - 受保护的类比私有类更容易访问,因此错误。

答案 1 :(得分:2)

PrivateInnerClass是OuterClassBase的私有 - 除了OuterClassBase之外没有人可以使用它(这是私有的意思)。

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

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

答案 2 :(得分: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();
    }
}