views:

134

answers:

2

Possible Duplicate:
Conditional operator cannot cast implicitly?

When writing a statement using the conditional operator, if the either of the expressions are numeric values they are always interpreted as int type. This makes a cast necessary to assign a short variable using this operator.

bool isTrue = true;
int intVal = isTrue ? 1 : 2;
short shortVal = isTrue ? 1 : 2;  // Compile error: Cannot implicitly convert type 'int' to 'short'. 

Shouldn't the compiler be able to know that both values are valid short values just as it would in a typical assignment statement(short shortVal = 1;)?

+3  A: 

This is because your 1 and 2 are ints. ?: returns the same type as 2nd and 3rd operands in your case.


Edit: At my VS2008 this works:

short x = true ? 1 : 2;

Did I do something wrong?


Edit: Indeed, the difference was that true was a compile-time constant. For non-constant expressions I got the same error message.

Vlad
Yes, but `short shortVal = 1;` does not give me the same compile error.
heavyd
@heavyd: indeed, see the edit.
Vlad
@heavyd: Given an example of `short x = 32767;`, the C# page for short says "In the preceding declaration, the integer literal 32767 is implicitly converted from int to short. If the integer literal does not fit into a short storage location, a compilation error will occur."
R. Bemrose
@Vlad, yes, I'm assuming the compiler is optimizing out the conditional expression in this case.
heavyd
If the condition is a compile time constant true and the consequence is a compile-time constant int, then the whole thing is treated as a constant int. But if the condition is not a compile-time constant then the expression is treated as a non-constant int, no matter what the consequence or alternative expressions are.
Eric Lippert
@heavyd: a decent compiler should be not allowed to be able to compile or not some code just because of optimization. So I hope your suggestion is wrong.
Vlad
@Eric: thanks! So the difference is between assigning a constant int and non-constant one? A constant int can be implicitly casted to short, whereas a non-constant cannot?
Vlad
@Vlad: It has nothing to do with optimization. A constant expression has to be one particular value. We don't say "well, this expression could be the constant 1 or the constant 2, and therefore it is the constant "one or two" and therefore it fits into a short". We could do that, but now consider if the conditional expression was more complex. How much information do you want us to carry around in each constant? "This constant could be one or two or four billion, but it is only four billion if x is true, and it is assigned to a short if x is false, therefore the assignment should be legal..."
Eric Lippert
@Vlad: A constant int that fits into a smaller integral type is allowed to be implicitly converted to that type, yes.
Eric Lippert
@Eric: my comment about the optimization was in response to the comment #4. I wonder what is the exact difference between compile time constants and non-constants. Is being a const just reserved to arithmetical expressions without function calls, or deterministic functions are allowed as well? `Math.sin(1) < 50 ? 1 : 2` is definitely a constant `1`, but does compiler go so deeply?
Vlad
@Vlad: Section 7.18 of the spec carefully defines exactly what a compile-time constant is.
Eric Lippert
@Eric: I see, thanks. In fact, no functions are allowed. :-(
Vlad
@Vlad: Indeed. Now, Sin is what we call a "pure" function; its output depends solely upon its inputs and it has no observable side effects, so we could in theory calculate it at compile time. Pure methods are also nice because you can automatically parallelize them and run them on other threads. We're doing some research into how to take advantage of methods that are known at compile time to be pure, but it's a tricky problem and it might be that nothing ever comes of it.
Eric Lippert
+3  A: 

It's not that the conditional operator (AKA ternary operator) always returns ints, it's because your literals are ints.

Unfortunately, C# doesn't appear to have a literal specifier for bytes or shorts (they do for longs, though).

R. Bemrose