views:

1585

answers:

5

I am curious as to why an implicit cast fails in...

int? someValue = SomeCondition ? ResultOfSomeCalc() : null;

and why I have to perform an explicit cast instead

int? someValue = SomeCondition ? ResultofSomeCalc() : (int?)null;

It seems to me that the compiler has all the information it need to make an implicit casting decision, no?

+13  A: 

The relevant section of the C# 3.0 spec is 7.13, the conditional operator:

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

Floetic
In summary, it does not take into account what type you are assigning to in the result of the operation. It merely tries to figure out the right side of the equation's type - with ignorance of Nullable types.
TheSoftwareJedi
But let's consider the case of ternary chaining. How else would it know?
Floetic
@DJ Floetic: it would start at the 'innermost' ?: operator, figure out the type of that result, then work its way out.
Michael Burr
+4  A: 

I also am annoyed that it can't infer the type based on the assignment, especially when it's a value type. There are reasons though when you get into object heirarchies.

If "ResultOfSomeCalc()" returned a "int?", then this would work. C# needs to figure out the type regardless of what is to the left of the assignment. So you are telling it that you'll return a null or an int - and the logic in the compiler doesn't exist to have it substitute a Nullable as a common denominator.

Notice that these variants DO work, and it may help you understand:

object someValue = true ? new Nullable<int>(ResultOfSomeCalc()) : null;

object someValue = true ? (int?)ResultOfSomeCalc() : null;

Hope this helps.

TheSoftwareJedi
Also a very good answer, I accepted DJ's and upvoted yours.
Tim Jarvis
+4  A: 

See also Why is this code invalid in C#?

harpo
Wow, what a terribly worded question. I would never have found that.
Tim Jarvis
A: 

If your function ResultofSomeCalc() returns int? then this will work.

If your function returns int, then the compiler issues the warning: Type of conditional expression cannot be determined because there is no implicit conversion between 'int' and ''
I'm guessing that is what you are seeing. Both expressions in the conditional operator "?:" must have the same type, or must be convertible to the same type via an implicit cast.

Change the return type of ResultOfSomeCalc to int?, or you will need to have the cast on the null expression.

+1  A: 

It sure seems like this is something the compiler should be able to figure out for itself, but there is one other way to do this, using the default keyword. It might be the tiniest bit less ugly than the cast:

int? someValue = SomeCondition ? ResultofSomeCalc() : default(int?);

This use of default doesn't seem to be well documented, but is does work. At least it keeps you from having to litter your code with magic values (I contend that null/zero/false/etc. are indeed magic values).

Mr. Putty