Nullable type issue with ?: Conditional Operator

60,022

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);
Share:
60,022

Related videos on Youtube

Nick Gotch
Author by

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, 2021

Comments

  • Nick Gotch
    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
      Stewart Johnson over 15 years
      You can save yourself a lot of typing by using DateTime? instead of Nullable<DateTime>.
  • Stewart Johnson
    Stewart Johnson over 15 years
    How does this answer his question??
  • Jeromy Irvine
    Jeromy Irvine over 15 years
    Nick 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
    Peter Ramos over 15 years
    Hence the FYI, offtopic but a nice thing to know.
  • DilbertDave
    DilbertDave almost 12 years
    Works 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
    Mishax about 11 years
    No, 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
    Mishax about 11 years
    @DilbertDave The information from MojoFilter's post is incorrect.
  • IS4
    IS4 over 9 years
    I'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> and DateTime 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 every null expression.)
  • IS4
    IS4 over 9 years
    Not true, default(DateTime) is not null, it is "1.1.0001 0:00:00", the same as new DateTime(0).
  • starmandeluxe
    starmandeluxe almost 7 years
    If it's been asked a bunch of times already, where's the duplicate question flag?
  • Scott Chamberlain
    Scott Chamberlain almost 7 years
    @starmandeluxe they all likely point here (at least that I how I got here)
  • newfurniturey
    newfurniturey over 5 years
    @IllidanS4, I didn't say that it's equal to null, only that by using default() you can assign it to a nullable value (as MSDN states). The examples I show demonstrate the versatility that it can be used with Nullable<DateTime>, DateTime?, and simply DateTime. If you believe this to be incorrect, can you provide a PoC where these fail?
  • IS4
    IS4 over 5 years
    Well, the questioner wanted to store null in the variable, not default(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 replace default(DateTime) with new DateTime() and it will do the same thing. Maybe default(DateTime?) is what you meant, since that is actually equal to null.