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?
The output is "Attempted to read protected memory. This is an indication that other memory is corrupt."
This is the strangest I've encountered by accident:
Used as follows:
Will throw a
NullReferenceException
. Turns out the multiple additions are compiled by the C# compiler to a call toString.Concat(object[])
. Prior to .NET 4, there is a bug in just that overload of Concat where the object is checked for null, but not the result of ToString():This is a bug by ECMA-334 §14.7.4:
Just found a nice little thing today:
This throws compile error.
The call to method 'Initialize' needs to be dynamically dispatched, but cannot be because it is part of a base access expression. Consider casting the dynamic arguments or eliminating the base access.
If I write base.Initialize(stuff as object); it works perfectly, however this seems to be a "magic word" here, since it does exactly the same, everything is still recieved as dynamic...
VB.NET, nullables and the ternary operator:
This took me some time to debug, since I expected
i
to containNothing
.What does i really contain?
0
.This is surprising but actually "correct" behavior:
Nothing
in VB.NET is not exactly the same asnull
in CLR:Nothing
can either meannull
ordefault(T)
for a value typeT
, depending on the context. In the above case,If
infersInteger
as the common type ofNothing
and5
, so, in this case,Nothing
means0
.Assign This!
This is one that I like to ask at parties (which is probably why I don't get invited anymore):
Can you make the following piece of code compile?
An easy cheat could be:
But the real solution is this:
So it's a little know fact that value types (structs) can reassign their
this
variable.The scoping in c# is truly bizarre at times. Lets me give you one example:
This fails to compile, because command is redeclared? There are some interested guesswork as to why it works that way in this thread on stackoverflow and in my blog.