为什么私有类的子类用户不能访问私有类的公共成员数据?以下内容对我来说似乎非常直观,因为它无法编译:
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允许代码编译......
答案 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();
}
}