无法访问同一基类的受保护成员

3

我有一个类似这样的东西:

class Node
{
    protected Node Parent
    {
        get; private set;
    }
}

class NodeDerived : Node
{
    void SomeMethod()
    {
        Node parentIterator = this.Parent;

        while (parentIterator != null)
        {
            // ... some logic

            parentIterator = parentIterator.Parent; // Here's the error
        }
    }
}

但是出于某种奇怪的原因,我无法访问parentIterator.Parent属性:

error CS1540: Cannot access protected member `Node.Parent' via a qualifier of type `Node'. The qualifier must be of type `NodeChild' or derived from it

为什么会发生这种情况呢?顺便提一下,我还发现虽然我可以访问this.Parent,但是我无法访问((Node) this).Parent


@asawyer:不,他正在尝试访问另一个对象的“Parent”属性。在这里,“base”无济于事。 - Jon Skeet
@JonSkeet 嗯,我明白了。我想今天早上需要喝更多的咖啡。 - asawyer
1个回答

5
从C# 5规范第3.5.3节可以得知:
当在声明它的类的程序文本之外访问受保护的实例成员,并且在声明它的程序的程序文本之外访问受保护的内部实例成员时,访问必须发生在从它所声明的类派生的类声明中。此外,要求通过该派生类类型的实例或从其构造的类类型进行访问。这种限制防止一个派生类访问其他派生类的受保护成员,即使这些成员是从同一基类继承而来。
因此,您可以访问任何NodeDerived对象的Parent属性。
NodeDerived derivedNode = ...;
Node parent = derivedNode.Parent;

...但是如果一个节点类型不是NodeDerived或其子类,则无法访问Parent属性。

使用this.Parent可以正常工作,因为this的编译时类型是NodeDerived

我猜你会想将Parent属性设为公共的 - 假设你希望这段代码能够与NodeDerived之外的节点一起使用。


这就是我修复它的方式,是的。感谢您的解释!我使用的是Mono 2.6,所以我没有查看C# 5文档,但我认为在这方面它没有改变。 - Max Yankov
@golergka:不,从C# 1.0开始,protected访问修饰符就是这样工作的。 - Jon Skeet
1
顺便问一句,虽然这个问题显然已经得到了回答,但你知道为什么他们设计它以那种方式工作吗? - Max Yankov
1
@golergka:我认为这个想法是,几个类可能具有相同的要求,但不想互相访问。我自己也不怎么使用protected。顺便说一下,Java的工作方式基本上是相同的。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接