Thursday, July 18, 2013

DateTime? and Null with the Ternary Operator

Yesterday, in a method that processes form data, I coded what I thought was a simple, concise statement to check for null input and set a DateTime? property in an MVC model to null. Well, apparently I was wrong because the compiler didn't like it at all...

My statement started out as this:

Object.NullableDt = (formCollection["date_input"] == null || formCollection["date_input"] == String.Empty ? null : DateTime.Parse(formCollection["date_input"].ToString());

Simple and straight forward, right? Apparently not! I got the ol' red underline in Visual Studio 2012 and (of course) my code wouldn't compile. The error was "Error 20" "Type of conditional expression cannot be determined because there is no implicit conversion between <null> and System.DateTime."

I sat there and stared at this error for a while, thinking to myself that it made NO sense that an data type that accepts null as a legitimate value should have any problems with this statement. I re-typed it several times, thinking maybe I had a typo but to no avail. Then I gave in and went to Google.

My first search result yielded a winner from good ol' Stack Overflow (original link) where it's explained by user SLaks that:
This doesn't work because the compiler will not insert an implicit conversion on both sides at once.
You want the compiler to convert a DateTime value to DateTime? on one side, and null to DateTime? on the other side.
This cannot happen.
If you explicitly convert either half to DateTime?, the other half will implicitly convert too.
Now, my personal opinion on this is that the compiler fails here and in a pretty epic way but, opinions aside, the suggested fix is easy to implement and works like a charm. Here's my original statement, modified to appease the unintelligent compiler:

Object.NullableDt = (formCollection["date_input"] == null || formCollection["date_input"] == String.Empty ? new DateTime?() : DateTime.Parse(formCollection["date_input"].ToString());

Note that what was once null is now new DateTime?() thus fulfilling the compiler's odd need to have an explicit type on one side of the statement. This could also be achieved by casting the right side of the statement to the appropriate type.

So, there you have it; Solving compiler stupidity with a few extra keystrokes. :-)

No comments: