Curtis
Curtis

Reputation: 411

Single line if statement generates cast error

new to C# so I'm having an issue with a short-hand statement. I want to convert...

if (m_dtLastLogin == null)
    drow["LastLogin"] = DBNull.Value;
else
    drow["LastLogin"] = m_dtLastLogin;

to

drow["LastLogin"] = (m_dtLastLogin == null) ? System.DBNull.Value : m_dtLastLogin;

The long-hand version works great, however, the short-hand version generates the error "Type of conditional cannot be determined because there is no implicit conversion between 'System.DBNull' and 'System.DateTime?'". My supporting code is basically...

private DateTime? m_dtLastLogin;
m_dtLastLogin = null;
DataRow drow;
drow = m_oDS.Tables["Users"].Rows[0];

Can someone help me with the short-hand here?

Upvotes: 0

Views: 2061

Answers (2)

Andre Loker
Andre Loker

Reputation: 8408

Well, the error message is pretty clear. The compiler needs to determine the type of the whole x?y:z expression. If y and z have the same type, it's easy. If y is convertible to z, the type of the expression is that of z, likewise if z is convertible to y the type is that of y.

In your case the type of y is DBNull, the type of y is the type of m_dtLastLogin (probably a datetime). Those two types cannot be converted into each other and have no common base type (except for Object), so the compiler doesn't know what to do.

You can help the compiler, however, by casting either y or z to object:

drow["LastLogin"] = (m_dtLastLogin == null) ? (object)System.DBNull.Value : m_dtLastLogin;

or

drow["LastLogin"] = (m_dtLastLogin == null) ? System.DBNull.Value : (object)m_dtLastLogin;

This way the whole expression has the type object, which can then be assigned to drow["LastLogin"].

Reference: C# language specification - http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf

Section 14.13, Conditional operator

Quote

The second and third operands of the ?: operator control the type of the conditional expression. Let X and Y be the types of the second and third operands. Then,

  • If X and Y are the same type, then this is the type of the conditional expression.

  • Otherwise, if an implicit conversion (§13.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.

  • Otherwise, if an implicit conversion (§13.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.

  • Otherwise, no expression type can be determined, and a compile-time error occurs.

Upvotes: 5

Hans Kesting
Hans Kesting

Reputation: 39274

Cast both to "object":

drow["LastLogin"] = (m_dtLastLogin == null) ? (object)System.DBNull.Value : 
    (object)m_dtLastLogin;

The conditional operator requires that both parts (the "then" and "else" part) evaluate to the same type, which will be the result type of the expression.

Your original version worked without casts, because it ended up in a field of type object.

Upvotes: 0

Related Questions