Wednesday, May 5, 2010

You don’t understand everything until you understand Nothing

Here’s a piece of code that might or might not do what you expect. (It depends on what you expect it to do.)

Dim someAge = "999"
Dim parsedAge As Integer? = If(someAge = "999", Nothing, Integer.Parse(someAge)) 


What will the parsedAge variable contain?


It will be a nullable integer with no value, right? Ehh, no wrong!

-So, what will it be?

Well, it will be a nullable integer – that’s the easy part – but it will have a value, zero (0)! Is this what you expected? It’s not what I expected when just gleening over the code. It’s not wrong or anything, it’s just that it’s not particularly intuitive.

It might be easier to see what happens here if we try to rewrite the same code in C#:

string someAge = “999”;
int? parsedAge = someAge == “999” ? null : int.Parse(someAge);

This will not even compile because the ternary operator must evaluate to a type and the compiler can’t figure out which type you want since an int value and null can never be of the same type.

So, why does it compile in VB? Well, because…

Nothing is not the same as null

- Huh? Nothing in VB is the same as null in C# right?

- Ehh, wrong!

Nothing is much more like the “default” keyword in C#. Nothing can be assigned to value type variables which will contain the default value of that type:

So let’s write C# code that is in fact equivalent to the VB code:

string someAge = “999”;
int? parsedAge = someAge == “999” ? default(int) : int.Parse(someAge);

Now, ofcourse “default(int)” will always return “0” so we could just as well write this:

int? parsedAge = someAge == “999” ? 0 : int.Parse(someAge);

Now it might be a bit more clear what happens; the ternary operator will always return an integer, either zero or the parsed string value, it will never return null and it will never return a nullable integer.

Now this is probably what threw me off to begin with: the result of the ternary operator is assigned nullable integer, leading us to believe that the result of the operator is a nullable integer when it infact never is. An int will be implicitly converted to a nullable int so the compiler will not complain here even though we technically have a type mismatch.

No comments:

Post a Comment