Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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

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.

Make your function ResultOfSomeCalc()'s return type as nullabel int like (int?)
int? someValue =(int?) SomeCondition ? ResultofSomeCalc() : (int?)null;

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top