views:

204

answers:

3
short s;
s = (EitherTrueOrFalse()) ? 0 : 1;

This fails with:

error CS0266: Cannot implicitly convert type 'int' to 'short'. An explicit conversion exists (are you missing a cast?)

Can anyone explain why this is so? The only thing I can think of is that the compiler doesn't look at the second value and doesn't know the range between the two, in the case I wrote something like

short s;
s = (EitherTrueOrFalse()) ? 0 : 65000;

Correct? The only fix is with an ugly cast?

Also, it seems C# does not have a type suffix for the short type. That's a pretty grave oversight IMO. Otherwise, that would've been a solution...

+6  A: 

The compiler has an implicit conversion from a constant expression to various primitive types (so long as the value is within the appropriate range), but here the expression isn't constant - it's just an int expression. It's pretty much the same as:

short s;
s = CallSomeMethodReturningInt32();

as far as the compiler is concerned.

There are two options - you could cast the whole expression, or cast each of the latter two operands:

short s = (EitherTrueOrFalse()) ? (short) 0 : (short) 1;

to make the overall expression type short. In this particular case, it's a pity that there isn't a numeric literal suffix to explicitly declare a short literal. Apparently the language designers did consider this, but felt it was a relatively rare situation. (I think I'd probably agree.)

The part about implicit constant conversions is from the C# 3.0 spec section 6.1.8:

6.1.8 Implicit constant expression conversions

An implicit constant expression conversion permits the following conversions:

  • A constant-expression (§7.18) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.
  • A constant-expression of type long can be converted to type ulong, provided the value of the constant-expression is not negative.
Jon Skeet
I wouldn't suggest to cast the whole expression, because this will be executed at runtime, while the cast of the constant is executed by the compiler.
Stefan Steinegger
Your explanation makes sense. And yeah, this is the first time I've come across it, so it's probably right to consider it rare or rare-ish. Still, a shame there's no suffix.
J F
A: 

Because the cast is done by the compiler, not at runtime, I wouldn't call it an ugly cast, I would call it a complicated syntax:

s = (EitherTrueOrFalse()) ? (short)0 : (short)1;

I mean, this is the way it is written in C#, even if it looks ugly.

See this blog article. See Marc Gravell's answer on that question.

Stefan Steinegger
A: 

I guess this has the same reason as this won't compile:

short s1 = GetShort1();
short s2 = GetShort2();
short s3 = s1 + s2;

I.e. that whenever short is used for something, it gets promoted to int.

erikkallen
No, that's not the reason. It's not "whenever short is used for something". In particular, if the 0 and 1 were actually s1 and s2, it would be fine. The reason addition fails in your case is because there's no addition operator defined for short, so the values are promoted to int.
Jon Skeet
Or, if you like, http://stackoverflow.com/questions/1547216/why-do-i-need-to-wrap-this-code-in-a-cast-to-short
RCIX