In a previous post, I discussed a bug in the Java Language Specification on super field access of protected fields. If you haven't read this yet, I would suggest to give it a read before you continue with this post. Thanks to a discussion with Alex Buckley (the new maintainer of the Java Language specification), there is now a proposal to fix this bug in an elegant way. I'll report on the solution and the nice discussion on the relation to super field accesses in bytecode later.
However, first I would like to illustrate the risk of reuse. While writing on issues in the Java Language Specification, I figured that the C# specification probably has the same issue. After all, C# features the same details of protected access. Consider the following two C# classes:
class A { protected int secret; } class B : A { public void f(A a) { a.secret = 5; } }
Due to the details of protected access, this example won't compile. The Mono C# compiler clearly explains the problem:
A.cs(17,5): error CS1540: Cannot access protected member `A.secret' via a qualifier of type `A'. The qualifier must be of type `B' or derived from it
Of course, C# also support access to fields of base classes (aka super classes). Indeed, checking the C# specification reveals that the definition of base access is exactly the same as super field access in Java. In Section 14.5.8 of the C# Language Specification (ECMA-334), the semantics of a base access expressions is defined in the following way:
"At compile-time, base-access expressions of the formbase.I
andbase[E]
are evaluated exactly as if they were written((B)this).I
and((B)this)[E]
, whereB
is the base class of the class or struct in which the construct occurs."
Compare this definition to the Java Language Specification:
"Suppose that a field access expressionsuper.name
appears within classC
, and the immediate super class ofC
is classS
. Thensuper.name
is treated exactly as if it had been the expression((S)this).name
."
The good thing about this reuse is that I can reuse the examples of my previous post as well. Consider the following two C# classes that compile without any problem:
class A { protected int secret; } class B : A { public void f() { base.secret = 5; } }
Next, consider the derivative of this example, where class B has been modified to refer to the field secret using (A) this
which is exactly the same as a reference through base
, according to the specification.
class B : A { public void f() { ((A) this).secret = 5; } }
Similar to Java, this class won't compile, due to the details of protected access in C#. Again, the Mono C# compiler explains the issue:
A.cs(13,7): error CS1540: Cannot access protected member `A.secret' via a qualifier of type `A'. The qualifier must be of type `B' or derived from it
This example shows that for C# the two expressions base.secret
and ((A) this).secret
are not evaluated in the same way, so the previously reported problem in the Java Language Specification also applies to the C# specification.
Now I have to figure out how to report issues in the C# specification ...
No comments:
Post a Comment