C# Stumper: Why does this code not compile?
Hey folks,
First off, I want to appologize for not having any activity on my blog for a while. I just got back from a wonderful 3 week vacation in Spain. Now that I'm back, rested and limber, here's a twisted peice of C# code which is gauranteed to turn your brain inside out.
Why does the compiler (correctly) give an error message on the override in the following code?
abstract class A<T>
{
public abstract T getT();
class B : A<B>
{
public override B getT()
{
throw new System.Exception("The method or operation is not implemented.");
}
}
}
I got this code from a coworker, and I must confess that the first time I saw it I was convinced that the behaviour was a compiler bug. It turns out that the compiler correctly diagnoses the problem, though even after seeing the error message it took me a while to figure out what's going on. I'll post a discussion in a couple of days.
Any Takers?
Peter
C# Guy
Comments
- Anonymous
November 09, 2005
The comment has been removed - Anonymous
November 09, 2005
This code crashes my installation of the RTM VS2005 IDE! It crashes it if I copy/paste the code in, or if I type it in. - Anonymous
November 09, 2005
Easy (at least if you read and grokked the fullness of Cyrus's (I think) similar quiz a few months ago which stumped me for DAYS).
The base class getT() returns A<B>.B (because B inherits from A<B>) while the derived class getT() returns A<T>.B (because it's taking the B from the containing scope). - Anonymous
November 09, 2005
The comment has been removed - Anonymous
November 09, 2005
tzagotta: The crash is probably the known infinite recursion bug in the IDE. It's something, I believe, that the C# IDE team's already looking into a hotfix for. - Anonymous
November 09, 2005
The comment has been removed - Anonymous
November 09, 2005
The comment has been removed - Anonymous
November 09, 2005
Teaches me to copy code from the RSS feed without looking at the comments first. I just lost a bit of work... - Anonymous
November 09, 2005
I'm running VS2005 beta2 (doing some WCF development) and I got the compiler error you spoke
about Peter. The problem is that since B is an internal class inside A<T>, in otherwords A<T>.B.
Your method signature for the override should be public override A<T>.B getT() since that's B's
actual type name. The code should look like this:
abstract class A<T>
{
public abstract T getT();
class B : A<B>
{
public override A<T>.B getT()
{
throw System.Exception("The method or operation is not implemented.");
}
}
}
If you use the code snippets feature of the IDE to create the implemenation of the override in
class B, you will get this signature:
public override B getT()
Which as mentioned is wrong. However, if you implement the class in VB.NET like Geoff did, then
the IDE gets your the right signature
' VB.NET Code
public overrides Function getT() as A(Of T).B
// C# code
public override A<T>.B getT()
(This seems to be in the case in VS2005 beta2. I'm not sure about RTM.)
Aren't generics fun? - Anonymous
November 09, 2005
Hey, how come my comments giving the answer aren't showing up? - Anonymous
November 09, 2005
I don't know why my posts aren't showing up, but I found Cyrus's quiz earlier that allowed me to figure this one out so quickly.
http://blogs.msdn.com/cyrusn/archive/2005/08/01/446431.aspx
If you read my comments on that one you can see my brain gradually turning inside out until the answer made sense ;) - Anonymous
November 09, 2005
Changing
public override B getT()
To
public override A<T>.B getT()
compiles properly. - Anonymous
November 09, 2005
Geoff: your code isn't identical. The return type of your overridden getT() is (in C#) A<T>.B, while the C# code Peter posted returns B from the overridden getT().
The reason the original C# code doesn't compile is that there are two B's:
1) A<B>.B, nested inside the A<B> that B derives from, in scope because of inheritance.
2) The outermost B, A<T>.B, the one that is being defined, in scope because of lexical nesting.
It appears that the inherited A<B>.B is what is being referred to when B is used nakedly, as in the example, when it should refer to the outer B, A<T>.B, which is the return-type of the overridden method.
I'm not intimiately familiar with the precedence of scope nesting in C#: it appears that the inheritance scope of a nested class comes ahead (or is pushed on the scope stack last, if you will) of the immediate outer lexical scope. Interesting. - Anonymous
November 10, 2005
Ok, I'm confused. I posted a whole bunch of comments, the first before 5pm EST yesterday giving the same correct solution that barrkel gave this morning and pointers to other relevant articles, and none of them showed up.
I'm making this post from IE in case the blog is blocking postings from Firefox...
What's wrong with my comments? :( - Anonymous
November 10, 2005
Barry: Yeah, I know mine's not identical, it's also correct laughs
OK, maybe not correct, but it's what the VB ide inserted for me with all it's autocomplete stuff. - Anonymous
November 10, 2005
I'm running VS2005 beta2 (doing some WCF development) and I got the compiler error you spoke
about Peter. The problem is that since B is an internal class inside A<T>, in otherwords A<T>.B.
Your method signature for the override should be public override A<T>.B getT() since that's B's
actual type name. The code should look like this:
abstract class A<T>
{
public abstract T getT();
class B : A<B>
{
public override A<T>.B getT()
{
throw System.Exception("The method or operation is not implemented.");
}
}
}
If you use the code snippets feature of the IDE to create the implemenation of the override in
class B, you will get this signature:
public override B getT()
Which as mentioned is wrong. However, if you implement the class in VB.NET like Geoff did, then
the IDE gets your the right signature
' VB.NET Code
public overrides Function getT() as A(Of T).B
// C# code
public override A<T>.B getT()
(This seems to be in the case in VS2005 beta2. I'm not sure about RTM.)
Aren't generics fun? - Anonymous
June 16, 2009
PingBack from http://topalternativedating.info/story.php?id=7787