We just ran across some bad code like this in our c#.net 4 codebase
DateTime myDate = someValue;
If (myDate==Null)
Do Something
It occurred to us that this condition will never occur.
How does the compiler handle these non-nullable struct comparisons?
Originally we were surprised that it would compile... but rationalized it on the point that you could certainly have a constant comparison like:
If(1==2)
Which would also never resolve true... but in that case the compiler can easily tell they are constants. Does it optimize or rollup non-nullable comparisons?
I punched this into LinqPad:
var t = new DateTime();
t.Dump();
(t == null).Dump();
And got this:
IL_0000: ldloca.s 00
IL_0002: initobj System.DateTime
IL_0008: ldloc.0
IL_0009: call LINQPad.Extensions.Dump
IL_000E: pop
IL_000F: ldc.i4.0
IL_0010: call LINQPad.Extensions.Dump
So yes, the compiler compiles it to the same as:
var t = new DateTime();
t.Dump();
(false).Dump();
Interestingly, if I create my own struct (TestStruct
) and try this:
TestStruct t;
(t == null).Dump();
... the compiler complains that I can't do an equals comparison between TestSruct
and null
.
In a comment, Paolo points to another StackOverflow post reporting this last phenomenon. Apparently by overloading the ==
and !=
operators, a value type becomes subject to an automatic conversion from t == null
to (Nullable<TestClass>)t == (Nullable<TestClass>)null
. If you haven't overloaded those operators, this implicit conversion doesn't make sense, so you get an error.