When using and learning about a programming language you are bound to, at some point, learn about some oddities in the programming language. Recently, I (once again) stumbled across the What’s the strangest corner case you’ve seen in C# or .NET? question on StackOverflow and I thought I would compile a list of some, of what I consider to be, surprising “features” of the C# language.
So here goes (in no particular order).
We all know about C#’s Nullable Value Types, but what happens when we compare them?
For some (unknown to me) reason, comparing two nullable value types (whose value is null) with
<= evaluate to false. It is false even though comparing with
== evaluate to true.
So apparently, a null nullable value type is equal to null, but it is not below or equal to null.
Let’s assume we have this enum and these methods
And then we call those methods a few times and look at the response
What is the significance of 0 vs 1?
The default value of an enum is the default value of its underlying type (in this case an integer), which is 0. In fact, since an enum’s underlying type can only be integral types (except char), the default value for all enums is 0. Because of the way this is handled, 0 (as the only value) can be implicitly converted to any enum, which is why 0 and 1 does not call the same overload.
The reason why
Convert.ToInt32(0) also calls the
object overload is because overload resolution happens at compile time, but the value returned from
Convert.ToInt32(0) is not known by the compiler.
This time we have the following classes:
What is the result of the following invocation of
There are two obvious possibilities: “1 Base” and “2 Derived”. Anyone who knows about method overriding in C#, will probably quickly figure out that it is the
Derived that is being called. This might cause many people to think that the result will be “2 Derived”.
Would you be surprised if I tell you that the result is “1 Derived”? The default value from the base class method is being used, even though it is the subclass’s method that is being called.
Once again, it is a compile time vs run-time issue. Default parameter values are resolved at compile time while method override resolution is handled at run-time.
That was a few cases that surprised me a bit when I learned about them. I might add more at some point. Until then, if you are interested, you can probably find more C# weirdness through Google.