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?
I'm not sure if you'd say this is a Windows Vista/7 oddity or a .Net oddity but it had me scratching my head for a while.
In Windows Vista/7 the file will actually be written to
C:\Users\<username>\Virtual Store\Program Files\my folder\test.txt
Have you ever thought the C# compiler could generate invalid CIL? Run this and you'll get a
TypeLoadException
:I don't know how it fares in the C# 4.0 compiler though.
EDIT: this is the output from my system:
Here's one I only found out about recently...
The above looks crazy at first glance, but is actually legal.No, really (although I've missed out a key part, but it isn't anything hacky like "add a class called
IFoo
" or "add ausing
alias to pointIFoo
at a class").See if you can figure out why, then: Who says you can’t instantiate an interface?
I'm arriving a bit late to the party, but I've got
threefourfive:If you poll InvokeRequired on a control that hasn't been loaded/shown, it will say false - and blow up in your face if you try to change it from another thread (the solution is to reference this.Handle in the creator of the control).
Another one which tripped me up is that given an assembly with:
if you calculate MyEnum.Red.ToString() in another assembly, and in between times someone has recompiled your enum to:
at runtime, you will get "Black".
I had a shared assembly with some handy constants in. My predecessor had left a load of ugly-looking get-only properties, I thought I'd get rid of the clutter and just use public const. I was more than a little surprised when VS compiled them to their values, and not references.
If you implement a new method of an interface from another assembly, but you rebuild referencing the old version of that assembly, you get a TypeLoadException (no implementation of 'NewMethod'), even though you have implemented it (see here).
Dictionary<,>: "The order in which the items are returned is undefined". This is horrible, because it can bite you sometimes, but work others, and if you've just blindly assumed that Dictionary is going to play nice ("why shouldn't it? I thought, List does"), you really have to have your nose in it before you finally start to question your assumption.
Consider this weird case:
If
Base
andDerived
are declared in the same assembly, the compiler will makeBase::Method
virtual and sealed (in the CIL), even thoughBase
doesn't implement the interface.If
Base
andDerived
are in different assemblies, when compiling theDerived
assembly, the compiler won't change the other assembly, so it will introduce a member inDerived
that will be an explicit implementation forMyInterface::Method
that will just delegate the call toBase::Method
.The compiler has to do this in order to support polymorphic dispatch with regards to the interface, i.e. it has to make that method virtual.
Here is an example of how you can create a struct that causes the error message "Attempted to read or write protected memory. This is often an indication that other memory is corrupt". The difference between success and failure is very subtle.
The following unit test demonstrates the problem.
See if you can work out what went wrong.