Why does null need an explicit type cast here? [duplicate]

The following code does not compile:

//int a = ...
int? b = (int?) (a != 0 ? a : null);

In order to compile, it needs to be changed to

int? b = (a != 0 ? a : (int?) null);

Since both b = null and b = a are legal, this doesn't make sense to me.

Why do we have to cast the null into an int? and why can't we simply provide an explicit type cast for the whole expression (which I know is possible in other cases)?


Solution 1:

From chapter 7.13 of the C# Language Specification:

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 (§6.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 (§6.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.

In your case, there is no implicit conversion from int to null nor the other way around. Your cast solves the problem, int is convertible to int?

Solution 2:

The both alternatives of ?: operator must be of the same type. Otherwise, the compiler cannot deduce the type of the whole conditional expression.

null is not an int, so you need to give a hint to the compiler that the resulting type is int?.


Edit: as the others pointed out, the two types don't need to be the same, but one of them should be castable to another (that another one will be the result type). See specs for more details.

Solution 3:

You can save yourself from casting if you use default(int?) instead of null.

int a = 42;
int? b = (a != 0 ? a : default(int?));