As explained in this question, and these articles, the following is not allowed:
public class A
{
protected virtual int X {get; private set;}
}
public class B : A
{
public int Add(A other)
{
return X + other.X;
}
}
Because if it was, and you had this:
public class C : A
{
protected override int X { get { return 4; } }
}
and then:
A c = new C();
B b = new B();
b.Add(c);
This is illegal because even though B
's access to X
means it knows that C
has the desired signature it's still not allowed to actually access the member.
So far, so good. But given the above, what I'm confused about is why I can do this:
public class A
{
protected virtual int X { get; private set; }
public int Add(A other)
{
return X + other.X;
}
}
And, therefore, this:
A c = new C();
A a = new A();
a.Add(c);
The definition of the protected keyword says:
A protected member is accessible within its class and by derived class instances.
But now the protected member on C
is being accessed from within A
, which is neither "its class" nor a "derived class instance", but a parent class. While A
obviously has access to the signature, the sibling example seems to indicate that that alone is not supposed to be sufficent, so why is protected
granting it access to the member?
This is defined by the specification:
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 is required to take place through an instance of the derived class type in which the access occurs.:
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
}
}
within A, it is possible to access x through instances of both A and B, since in either case the access takes place through an instance of A or a class derived from A. However, within B, it is not possible to access x through an instance of A, since A does not derive from B.
The entire point of this being the fact that I wouldn't want anyone of class C
, although allowed to derive from my class A
, access my "internal" state in class B
, although both of them share the fact that they are derivatives of class A
.
As the author of C
, I get to choose my base class. So I've found A
, I've read its documentation, I know how and why it will invoke any of my inherited protected
members (and, of course, I have options such as sealed
or protecting my constructors to control which classes, if any, can derive from my C
). That's all I really have to think about (outside of reflection/full control scenarios, but once reflection is in the picture all bets are off).
What I don't have to worry about is someone else deciding they want to invoke those protected
methods. Which (under your proposed modification), they'd be able to do by simply creating their own class, B
, derived from A
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With