tags:

views:

1337

answers:

9

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 Nullabale 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?

+13  A: 

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.

Andrew Hare
I know I can work around it, I'm just curious as to why this is happening?
BFree
+1  A: 
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.

Martin Peck
Doh! Andrew got their first. +1 to him.
Martin Peck
A: 

Try one of these:

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

int? x = GetBoolValue() ? 10 : (int?)null;
John Gietzen
+1  A: 

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.

Daniel Brückner
+1  A: 

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;
Justin Niessner
+22  A: 

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

GetBoolValue() ? (int?)10 : null    // #1
GetBoolValue() ? 10 : (int?)null    // #2
LukeH
Hmm.. never knew that. Thanks!!
BFree
You can also write `new int?()`.
SLaks
+1  A: 

It's because the compiler determines the type of the conditional operator by it's 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.

Guffa
+3  A: 

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. Here's my article on it:

http://blogs.msdn.com/ericlippert/archive/2006/05/24/type-inference-woes-part-one.aspx

Eric Lippert