There is no implicit conversion between null and datetime

Viewed 20923

Following code read a piece data from given DataRow(modelValue) and parse it to a nullable DateTime instance.

Question: Please see the code sections under L1 & L2 where both are technically equal (If i am not making any schoolboy error). However, L1 works as expected but not L2. I am getting

there is no implicit conversion between null and datetime

when I execute the code under L2. Can someone advise me ?

        DateTime? CallBack;

        var callBackDate = modelValue["CallBack"] == DBNull.Value ? null : modelValue["CallBack"].ToString();
        //Parsing
        DateTime cdate;
        if (!DateTime.TryParse(callBackDate, out cdate))
            cdate = DateTime.MinValue;


        //L1
        if (cdate==DateTime.MinValue)
            CallBack = null;
        else
           CallBack = cdate.Date;

       //L2  
       CallBack = cdate == DateTime.MinValue?null:cdate.Date;
4 Answers

You need to tell the compiler that the null should be treated as DateTime?. Otherwise the compiler doesn't know what type null is.

CallBack = cdate == DateTime.MinValue ? (DateTime?)null : cdate.Date;

(Z) ? X : Y

The ternary operator requires that an implicit conversion exists from the second operand (X) to the third operand (Y), or from Y to X.

Since null cannot be implicitly converted to DateTime, nor DateTime to null, the expression cannot be evaluated. More on this: Type inference woes by Eric Lippert.

You have to cast null to DateTime?. By doing so, X will be of type DateTime? and Y will be of type DateTime. Since there is an implicit conversion from DateTime to DateTime?, the expression can be evaluated, and it will return a value of type DateTime?.

Alternatively, and following the same logic, you could also cast the third operand Y to DateTime?.

Why don't you use the DataRow.Field extension method which supports nullable types in the first place?

DateTime? CallBack = modelValue.Field<DateTime?>("CallBack");

But since you actually have a string column you need to parse it first:

DateTime? CallBack = null;
string callBackDate = modelValue.Field<string>("CallBack");
if(!string.IsNullOrWhiteSpace(callBackDate))
{
    DateTime cdate;
    if(DateTime.TryParse(callBackDate, out cdate))
        CallBack = cdate;
}

That's all.

You could do the following:

        DateTime aDateTime = DateTime.MinValue;
        DateTime? aNullableDateTime = aDateTime == DateTime.MinValue ? null : new DateTime?(aDateTime.Date);

which uses the Nullable(Of T) structure.

Related