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.Iandbase[E]are evaluated exactly as if they were written((B)this).Iand((B)this)[E], whereBis 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.nameappears within classC, and the immediate super class ofCis classS. Thensuper.nameis 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