Why can't I access C# protected members except like this?

BCS picture BCS · Feb 20, 2009 · Viewed 30.5k times · Source

This code:

abstract class C
{
    protected abstract void F(D d);
}

class D : C
{
    protected override void F(D d) { }

    void G(C c)
    {
        c.F(this);
    }
}

Generates this error:

Cannot access protected member 'C.F(D)' via a qualifier of type 'C'; the qualifier must be of type 'D' (or derived from it)

What in the world were they thinking? (Would altering that rule break something?) And is there a way around that aside from making F public?


Edit: I now get the reason for why this is (Thanks Greg) but I'm still a bit perplexed as to the rational; given:

class E : C
{
    protected override void F(D d) { }
}  

Why shouldn't D be able to be able to call E.F?


The error message is edited so I might have put a typo in there.

Answer

Greg Beech picture Greg Beech · Feb 20, 2009

The reason this doesn't work is because C# doesn't allow cross-hierarchy calling of protected methods. Say there was a class E that also derived from C:

  C
 / \
D   E

Then the reference you're trying to call the method on could actually be an instance of type E and thus the method could resolve at runtime to E.F. This is not permitted in C# as D cannot call E's protected methods, because E is in another branch of the hierarchy, i.e.

var d = new D();
var e = new E();
d.G(e); // oops, now this will call E.F which isn't allowed from D

This makes sense because the keyword protected means the member "is accessible within its class and by derived class instances" and E.F is not a member of D.