C# 为什么家长可以访问子类';受保护成员,如果兄弟姐妹可以';T

C# 为什么家长可以访问子类';受保护成员,如果兄弟姐妹可以';T,c#,inheritance,C#,Inheritance,如和中所述,不允许出现以下情况: public class A { protected virtual int X {get; private set;} } public class B : A { public int Add(A other) { return X + other.X; } } 因为如果是的话,你有这个: public class C : A { protected override int X { get

如和中所述,不允许出现以下情况:

public class A
{
    protected virtual int X {get; private set;}
}

public class B : A
{
    public int Add(A other)
    {
        return X + other.X;
    }
}
因为如果是的话,你有这个:

public class C : A 
{  
    protected override int X { get { return 4; } }
}
然后:

A c = new C();
B b = new B();
b.Add(c);
这是非法的,因为即使
B
访问
X
意味着它知道
C
具有所需的签名,但仍然不允许实际访问该成员


到目前为止,一切顺利。但鉴于上述情况,我感到困惑的是,我为什么可以这样做:

public class A
{
    protected virtual int X { get; private set; }

    public int Add(A other)
    {
        return X + other.X;
    }
}
因此,这:

A c = new C();
A a = new A();
a.Add(c);
报告说:

受保护的成员可以在其类内以及由派生类实例访问

但是现在,
C
上的受保护成员是从
A
中访问的,它既不是“其类”,也不是“派生类实例”,而是父类。虽然
A
显然可以访问签名,但兄弟姐妹示例似乎表明,仅此一项并不足够,那么为什么
受保护
授予其成员访问权限?

这是由以下内容定义的:

在程序文本之外访问受保护的实例成员时 声明它的类的,并且当受保护的内部 在中的程序文本之外访问实例成员 声明后,需要通过进行访问 发生访问的派生类类型的实例。

在A中,可以通过A和的实例访问x B、 因为在任何一种情况下,访问都是通过 A或从A派生的类。但是,在B中,不可能 通过A的实例访问x,因为A不是从B派生的。


这一点的全部要点是,我不想让
C类的任何人,尽管可以从我的类
A
派生,但可以访问我在类
B
中的“内部”状态,尽管他们都是
A
类的派生,作为
C
的作者,我可以选择我的基类。因此,我找到了
A
,阅读了它的文档,我知道它将如何以及为什么调用我继承的
受保护的
成员(当然,我还有
密封的
或保护构造函数等选项来控制哪些类(如果有的话)可以从
C
派生)。这就是我真正需要考虑的(在反射/完全控制场景之外,但是一旦反射出现在图片中,所有的赌注都会被取消)


我不必担心的是其他人决定调用那些
受保护的
方法。这(在你建议的修改下),他们可以通过创建自己的类,
B
,从
A

派生而来,也许我只是变得很密集(这不是第一次),但我看不到你对类“C”的定义。您只发布了一些代码,说明了根据规则C不能是什么,因此我看不到您关于“C”行为的说明。
A
X
的“类”,并且不清楚您试图在
X
的声明和“签名”之间做出什么区别。在第二个示例中,您的
Add
方法在
A
中声明,因此您正在访问声明类中的
protected
成员
A.X
,这在
protected
@DavidW
C
的定义中是允许的
C
是合法的,它是
B中的
other.X
。Add
不是合法的,并且
C
被用作一个示例的一部分,说明如果
other.X
是合法的,你可以做什么。@Lee肯定那句话中的“类”必须指的是实际运行时类
C
,而不是静态类
A
,否则,为什么第一个例子是非法的?我想指出的区别是,
B
知道
C
有一个
intx
属性,只是不允许调用它。我在你的页面上没有看到这句话linked@BenAaronson-该页面未链接到规范。出于某种深不可测的原因,在.NET 1.1之外,他们决定只将规范放在您必须下载(或使用VS安装)的word文档中,而不是放在web上。@BenAaronson我无意中链接到了错误的链接。修正了。@YuvalItzchakov好的,谢谢!很高兴知道它有文档记录,但这似乎更像是对问题的陈述,而不是解释。我会让它打开一段时间,看看我是否有任何理由来解释为什么会这样(我知道这通常是一个很难回答的问题)。如果没有,我就接受this@BenAaronson我添加了一个解释,解释为什么这是不可能的。不是提议的修改!这只是一个对比的例子。我想这个答案很符合埃里克·利珀特的描述:这是一个很好的解释情况的方法。太好了。@BenAaronson-是的,我知道你不一定在寻找/要求改变。我只是想找到一些“如果规则不是这样的,并且您的第一个示例中的代码没有编译”的简写
public class A
{
   protected int x;
   static void F(A a, B b)
   {
      a.x = 1;      // Ok
      b.x = 1;      // Ok
   }
}

public class B : A
{
   static void F(A a, B b) 
   {
      a.x = 1;      // Error, must access through instance of B
      b.x = 1;      // Ok
   }
}