Surprising ‘protected’ behavior


size=2>There’s a subtle but important
difference between protected access in unmanaged C++ and protected access (i.e.
family) in the CLR.  The difference is due to the CLR’s ability to build
security guarantees on top of type safety.
style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


size=2>  style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


size=2>Imagine you had a bifurcated
hierarchy:
style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


size=2>  style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


style="FONT-FAMILY: 'Lucida Console'">       Class
A { protected M } style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


style="FONT-FAMILY: 'Lucida Console'">      

              \ style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


style="FONT-FAMILY: 'Lucida Console'">Class G :
A           Class X :
A style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


face=Tahoma>  style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


face=Tahoma>There is no relationship
between X and G, except for the fact that they both derive from A.  We
don’t allow X to access A.M on instances of type G and we don’t allow G to
access A.M on instances of type X.  Instead, X can only access A.M on
instances of X and instances that are subtypes of X.
style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


face=Tahoma>  style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">


face=Tahoma>The most efficient way
for us to enforce this is to require a cast to X before accessing A.M from any
of X’s methods.  Of course, we only require this in verifiable
code.


style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'">