Nullable types and the ternary operator: why is `? 10 : null` forbidden?

C#.NetNullableConditional Operator

C# Problem Overview


I just came across a weird error:

private bool GetBoolValue()
{
    //Do some logic and return true or false
}

Then, in another method, something like this:

int? x = GetBoolValue() ? 10 : null;

Simple, if the method returns true, assign 10 to the Nullableint x. Otherwise, assign null to the nullable int. However, the compiler complains:

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

Am I going nuts?

C# Solutions


Solution 1 - C#

The compiler first tries to evaluate the right-hand expression:

GetBoolValue() ? 10 : null

The 10 is an int literal (not int?) and null is, well, null. There's no implicit conversion between those two hence the error message.

If you change the right-hand expression to one of the following then it compiles because there is an implicit conversion between int? and null (#1) and between int and int? (#2, #3).

GetBoolValue() ? (int?)10 : null    // #1
GetBoolValue() ? 10 : (int?)null    // #2
GetBoolValue() ? 10 : default(int?) // #3

Solution 2 - C#

Try this:

int? x = GetBoolValue() ? 10 : (int?)null;

Basically what is happening is that conditional operator is unable to determine the "return type" of the expression. Since the compiler implictitly decides that 10 is an int it then decides that the return type of this expression shall be an int as well. Since an int cannot be null (the third operand of the conditional operator) it complains.

By casting the null to a Nullable<int> we are telling the compiler explicitly that the return type of this expression shall be a Nullable<int>. You could have just as easily casted the 10 to int? as well and had the same effect.

Solution 3 - C#

Incidentally, the Microsoft implementation of the C# compiler actually gets the type analysis of the conditional operator wrong in a very subtle and interesting (to me) way. My article on it is Type inference woes, part one (2006-05-24).

Solution 4 - C#

Try this:

int? result = condition ? 10 : default(int?);

Solution 5 - C#

Try one of these:

int? x = GetBoolValue() ? (int?)10 : null;

int? x = GetBoolValue() ? 10 : (int?)null;

Solution 6 - C#

The problem is that the ternary operator is inferring type based on your first parameter assignment...10 in this case, which is an int, not a nullable int.

You might have better luck with:

int? x = GetBoolValue() (int?)10 : null;

Solution 7 - C#

int? x = GetBoolValue() ? 10 : (int?)null;

The reason you see this is because behind the scenes you're using Nullable and you need to tell C# that your "null" is a null instance of Nullable.

Solution 8 - C#

Just add an explict cast.

int? x = GetBoolValue() ? 10 : (int?)null;

It is the ternary operator that gets confused - the second argument is an integer and so is the third argument exspected to be an integer, too, and null does not fit.

Solution 9 - C#

It's because the compiler determines the type of the conditional operator by its second and third operand, not by what you assign the result to. There is no direct cast between an integer and an null reference that the compiler can use to determine the type.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBFreeView Question on Stackoverflow
Solution 1 - C#LukeHView Answer on Stackoverflow
Solution 2 - C#Andrew HareView Answer on Stackoverflow
Solution 3 - C#Eric LippertView Answer on Stackoverflow
Solution 4 - C#UnknownView Answer on Stackoverflow
Solution 5 - C#John GietzenView Answer on Stackoverflow
Solution 6 - C#Justin NiessnerView Answer on Stackoverflow
Solution 7 - C#Martin PeckView Answer on Stackoverflow
Solution 8 - C#Daniel BrücknerView Answer on Stackoverflow
Solution 9 - C#GuffaView Answer on Stackoverflow