3

I have something like this:

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
        }
    }
}

But for some strange reason, I can't access parentIterator.Parent property:

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

Why is this happening? By the way, I also discovered that while I can access this.Parent, I can't access ((Node) this).Parent.

Max Yankov
  • 12,551
  • 12
  • 67
  • 135
  • @asawyer: No, he's trying to access the `Parent` property of a different object. `base` won't help here. – Jon Skeet Jan 30 '14 at 13:08
  • @JonSkeet Hm I see. Need more coffee this morning I think. – asawyer Jan 30 '14 at 13:08
  • I suspect this is a duplicate of [What's the real reason for preventing protected member access through a base/sibling class?](http://stackoverflow.com/q/1904782/18192). Relevant [Eric Lippert Blog Post](http://blogs.msdn.com/b/ericlippert/archive/2010/01/14/why-cant-i-access-a-protected-member-from-a-derived-class-part-six.aspx) – Brian Jan 30 '14 at 16:15

1 Answers1

5

From the C# 5 spec, section 3.5.3:

When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access must take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class.

So you're fine to access the Parent property of any NodeDerived object:

NodeDerived derivedNode = ...;
Node parent = derivedNode.Parent;

... but you can't access the Parent property for a node type which isn't NodeDerived or a subclass.

Using this.Parent works because the compile-time type of this is NodeDerived.

I suspect you'll want to make your Parent property public - assuming that you want this code to work with nodes other than NodeDerived.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • That's how I fixed it, yes. Thanks for the explanation! I use Mono 2.6, so I didn't look in the C# 5 documentation, but I think it didn't change in that regard. – Max Yankov Jan 30 '14 at 13:08
  • @golergka: No, protected access has worked this way from C# 1.0. – Jon Skeet Jan 30 '14 at 13:09
  • 1
    By the way, although this question is clearly answered, do you know WHY they designed for it to work that way? – Max Yankov Jan 30 '14 at 13:10
  • 1
    @golergka: I believe the idea is that several classes may have the same requirements, but not want to give access *to each other*. I can't say I use `protected` very much myself. Java works pretty much the same way, by the way. – Jon Skeet Jan 30 '14 at 13:13