Nullable type issue with ?: Conditional Operator
Solution 1
The compiler is telling you that it doesn't know how convert null
into a DateTime
.
The solution is simple:
DateTime? foo;
foo = true ? (DateTime?)null : new DateTime(0);
Note that Nullable<DateTime>
can be written DateTime?
which will save you a bunch of typing.
Solution 2
FYI (Offtopic, but nifty and related to nullable types) we have a handy operator just for nullable types called the null coalescing operator
??
Used like this:
// Left hand is the nullable type, righthand is default if the type is null.
Nullable<DateTime> foo;
DateTime value = foo ?? new DateTime(0);
Solution 3
It's because in a ternary operator, the two values must resolve to the same type.
Solution 4
I know this question was asked in 2008 and it is now 5 years later but the answer marked as an answer does not satisfy me. The real answer is that DateTime is a struct, and as a struct it is not compatible with null. You have two ways of solving that:
First is to make null compatible with DateTime (for instance, cast null to DateTime? as the gentleman with 70 upvotes suggests, or cast null to Object or to ValueType).
The second is to make the DateTime compatible with null (for instance, cast DateTime to DateTime?).
Solution 5
Another solution similar to the accepted is to use C#'s default
keyword. While defined using generics, it is actually applicable to any type.
Example usage applied to the OP's question:
Nullable<DateTime> foo;
foo = true ? default(DateTime) : new DateTime(0);
Example usage with the current accepted answer:
DateTime? foo;
foo = true ? default(DateTime) : new DateTime(0);
Also, by using default
, you do not need to specify the variable as nullable
in order to assign it a null
value. The compiler will auto-assign the specific variable-type's default value and no error will be encountered. Example:
DateTime foo;
foo = true ? default(DateTime) : new DateTime(0);
Related videos on Youtube
Nick Gotch
I've been a software engineer in a variety of industries over the past 15 years. The majority of that time has been developing business software for academic, financial, healthcare, and management services, primarily in C#.NET (starting with .NET 1.1) and Python, but also with a fair amount of Perl and a mix of other languages (C++, VB.NET, Lua, etc.). I've also spent about 5 years of that time in the mobile games industry, working on the Android release of Fieldrunners and the server backend for Fieldrunners Attack!.
Updated on April 08, 2021Comments
-
Nick Gotch about 3 years
Could someone explain why this works in C#.NET 2.0:
Nullable<DateTime> foo; if (true) foo = null; else foo = new DateTime(0);
...but this doesn't:
Nullable<DateTime> foo; foo = true ? null : new DateTime(0);
The latter form gives me an compile error "Type of conditional expression cannot be determined because there is no implicit conversion between '<null>' and 'System.DateTime'."
Not that I can't use the former, but the second style is more consistent with the rest of my code.
-
Stewart Johnson over 15 yearsYou can save yourself a lot of typing by using DateTime? instead of Nullable<DateTime>.
-
-
Stewart Johnson over 15 yearsHow does this answer his question??
-
Jeromy Irvine over 15 yearsNick is trying to assign null to foo if some condition is true. The null coalesce will assign DateTime(0) to value if foo is null. The two are completely unrelated.
-
Peter Ramos over 15 yearsHence the FYI, offtopic but a nice thing to know.
-
DilbertDave almost 12 yearsWorks well enough but now you can't null check foo - it will always have a value. No way around this though - as MojoFilter says "It's because in a ternary operator, the two values must be the same type."
-
Mishax about 11 yearsNo, they don't have to be the same type. Either the second operand must be implicitly convertible to the type of the third operand or the other way around.
-
Mishax about 11 years@DilbertDave The information from MojoFilter's post is incorrect.
-
IS4 over 9 yearsI'd add that the compiler tries to guess the resulting type of the ternary operation not by looking at the variable to which it is assigned, but by looking at the operands instead. It finds
<null>
andDateTime
and instead of finding the common ancestor type, it just tries to find a conversion between each other. (Extra bit: C# recognizes a<null>
type, i.e. the type of everynull
expression.) -
IS4 over 9 yearsNot true,
default(DateTime)
is not null, it is "1.1.0001 0:00:00
", the same asnew DateTime(0)
. -
starmandeluxe almost 7 yearsIf it's been asked a bunch of times already, where's the duplicate question flag?
-
Scott Chamberlain almost 7 years@starmandeluxe they all likely point here (at least that I how I got here)
-
newfurniturey over 5 years@IllidanS4, I didn't say that it's equal to
null
, only that by usingdefault()
you can assign it to anullable
value (as MSDN states). The examples I show demonstrate the versatility that it can be used withNullable<DateTime>
,DateTime?
, and simplyDateTime
. If you believe this to be incorrect, can you provide a PoC where these fail? -
IS4 over 5 yearsWell, the questioner wanted to store
null
in the variable, notdefault(DateTime)
, so this is misleading at best. This is not "versatile" as you imply, since the expression as a whole has still the same type -DateTime
, and you can replacedefault(DateTime)
withnew DateTime()
and it will do the same thing. Maybedefault(DateTime?)
is what you meant, since that is actually equal tonull
.