I collect a few corner cases and brain teasers and would always like to hear more. The page only really covers C# language bits and bobs, but I also find core .NET things interesting too. For example, here's one which isn't on the page, but which I find incredible:
string x = new string(new char[0]);
string y = new string(new char[0]);
Console.WriteLine(object.ReferenceEquals(x, y));
I'd expect that to print False - after all, "new" (with a reference type) always creates a new object, doesn't it? The specs for both C# and the CLI indicate that it should. Well, not in this particular case. It prints True, and has done on every version of the framework I've tested it with. (I haven't tried it on Mono, admittedly...)
Just to be clear, this is only an example of the kind of thing I'm looking for - I wasn't particularly looking for discussion/explanation of this oddity. (It's not the same as normal string interning; in particular, string interning doesn't normally happen when a constructor is called.) I was really asking for similar odd behaviour.
Any other gems lurking out there?
There is something really exciting about C#, the way it handles closures.
Instead of copying the stack variable values to the closure free variable, it does that preprocessor magic wrapping all occurences of the variable into an object and thus moves it out of stack - straight to the heap! :)
I guess, that makes C# even more functionally-complete (or lambda-complete huh)) language than ML itself (which uses stack value copying AFAIK). F# has that feature too, as C# does.
That does bring much delight to me, thank you MS guys!
It's not an oddity or corner case though... but something really unexpected from a stack-based VM language :)
C# Accessibility Puzzler
The following derived class is accessing a private field from its base class, and the compiler silently looks to the other side:
The field is indeed private:
Care to guess how we can make such code compile?
.
.
.
.
.
.
.
Answer
The trick is to declare
Derived
as an inner class ofBase
:Inner classes are given full access to the outer class members. In this case the inner class also happens to derive from the outer class. This allows us to "break" the encapsulation of private members.
Few years ago, when working on loyality program, we had an issue with the amount of points given to customers. The issue was related to casting/converting double to int.
In code below:
does i1 == i2 ?
It turns out that i1 != i2. Because of different rounding policies in Convert and cast operator the actual values are:
It's always better to call Math.Ceiling() or Math.Floor() (or Math.Round with MidpointRounding that meets our requirements)
What will this function do if called as
Rec(0)
(not under the debugger)?Answer:
This is because the 64-bit JIT compiler applies tail call optimisation, whereas the 32-bit JIT does not.
Unfortunately I haven't got a 64-bit machine to hand to verify this, but the method does meet all the conditions for tail-call optimisation. If anybody does have one I'd be interested to see if it's true.
The following might be general knowledge I was just simply lacking, but eh. Some time ago, we had a bug case which included virtual properties. Abstracting the context a bit, consider the following code, and apply breakpoint to specified area :
While in the
Derived
object context, you can get the same behavior when addingbase.Property
as a watch, or typingbase.Property
into the quickwatch.Took me some time to realize what was going on. In the end I was enlightened by the Quickwatch. When going into the Quickwatch and exploring the
Derived
object d (or from the object's context,this
) and selecting the fieldbase
, the edit field on top of the Quickwatch displays the following cast:Which means that if base is replaced as such, the call would be
for the Watches, Quickwatch and the debugging mouse-over tooltips, and it would then make sense for it to display
"AWESOME"
instead of"BASE_AWESOME"
when considering polymorphism. I'm still unsure why it would transform it into a cast, one hypothesis is thatcall
might not be available from those modules' context, and onlycallvirt
.Anyhow, that obviously doesn't alter anything in terms of functionality,
Derived.BaseProperty
will still really return"BASE_AWESOME"
, and thus this was not the root of our bug at work, simply a confusing component. I did however find it interesting how it could mislead developpers which would be unaware of that fact during their debug sessions, specially ifBase
is not exposed in your project but rather referenced as a 3rd party DLL, resulting in Devs just saying :From a question I asked not long ago:
Conditional operator cannot cast implicitly?
Given:
Where
aBoolValue
is assigned either True or False;The following will not compile:
But this would:
The answer provided is pretty good too.