230

Why does this not compile?

int? number = true ? 5 : null;

Type of conditional expression cannot be determined because there is no implicit conversion between 'int' and <null>

gitsitgo
  • 6,589
  • 3
  • 33
  • 45
davidhq
  • 4,660
  • 6
  • 30
  • 40
  • Best explanation and example... [http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-is-10-null-forbidden?answertab=active#tab](http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-is-10-null-forbidden?answertab=active#tab-top)-top – Parth Savadiya Feb 06 '17 at 08:19

4 Answers4

434

The spec (§7.14) says that for conditional expression b ? x : y, there are three possibilities, either x and y both have a type and certain good conditions are met, only one of x and y has a type and certain good conditions are met, or a compile-time error occurs. Here, "certain good conditions" means certain conversions are possible, which we will get into the details of below.

Now, let's turn to the germane part of the spec:

If only one of x and y has a type, and both x and y are implicitly convertible to that type, then that is the type of the conditional expression.

The issue here is that in

int? number = true ? 5 : null;

only one of the conditional results has a type. Here x is an int literal, and y is null which does not have a type and null is not implicitly convertible to an int1. Therefore, "certain good conditions" aren't met, and a compile-time error occurs.

There are two ways around this:

int? number = true ? (int?)5 : null;

Here we are still in the case where only one of x and y has a type. Note that null still does not have a type yet the compiler won't have any problem with this because (int?)5 and null are both implicitly convertible to int? (§6.1.4 and §6.1.5).

The other way is obviously:

int? number = true ? 5 : (int?)null;

but now we have to read a different clause in the spec to understand why this is okay:

If x has type X and y has type Y then

  • 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.

  • 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.

Here x is of type int and y is of type int?. There is no implicit conversion from int? to int, but there is an implicit conversion from int to int? so the type of the expression is int?.

1: Note further that the type of the left-hand side is ignored in determining the type of the conditional expression, a common source of confusion here.

Community
  • 1
  • 1
jason
  • 236,483
  • 35
  • 423
  • 525
95

null does not have any identifiable type - it just needs a little prodding to make it happy:

int? number = true ? 5 : (int?)null;
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 5
    Or you can do `int? number = true ? 5 : null as int?;` – Brad M Aug 15 '13 at 19:49
  • 1
    Nice answer nailing the point. Nice related reading: http://ericlippert.com/2013/05/30/what-the-meaning-of-is-is/ – Benjamin Gruenbaum Aug 15 '13 at 20:01
  • The issue is *not* that `null` doesn't have an identifiable type. The issue is that there is no implicit conversion from `null` to `int`. Details [here](http://stackoverflow.com/a/18260915/45914). – jason Aug 15 '13 at 20:11
  • the interesting thing is that `int? number = true ? 5 : (int?)null;` and `int? number = true ? (int?)5 : null;` both compile!! Scratch, scratch – davidhq Aug 15 '13 at 20:19
  • 2
    I cover *exactly* why this happens in my [answer](http://stackoverflow.com/a/18260915/45914). – jason Aug 15 '13 at 20:22
  • yes, I see it.. thank you both! I accepted your answer, Jason, because it's more throughout – davidhq Aug 15 '13 at 20:23
  • @David Krmpotic: I feel bad saying this because Marc is a smart guy and I've learned a *lot* from his answers in the past, but this answer is not just less thorough, it misidentifies the issue. `null` not having an identifiable type is okay; `null` not being implicitly convertible to `int` is the issue. – jason Aug 15 '13 at 20:50
  • I see! Thank you both - you for correctly explaining in depth and Marc for giving the hint about what works even though the explanation is "not perfect" ;) – davidhq Aug 15 '13 at 21:07
  • This is the most concrete and simple answer to the question, Mr Gravell. Bravo! – Ignotus Apr 25 '20 at 15:58
16

In C# 9 this is now allowed blog

Target typed ?? and ?

Sometimes conditional ?? and ?: expressions don’t have an obvious shared type between the branches. Such cases fail today, but C# 9.0 will allow them if there’s a target type that both branches convert to:

Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type

Or your example:

// Allowed in C# 9.
int? number = true ? 5 : null;
Tobias
  • 2,089
  • 2
  • 26
  • 51
WBuck
  • 5,162
  • 2
  • 25
  • 36
6

The 5 is an int, and null cannot be implicitly converted to int.

Here are ways to work around the issue:

int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();

int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;

int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;

int? num = true ? new int?(5) : null;

Also, anywhere you see int? you could use Nullable<int> instead.

Andrew
  • 18,680
  • 13
  • 103
  • 118