19

I have a code:

static short Sum(short a, short b)
        {
            return a + b;
        }

And it does not compile, saynig cannot convert 'int' to 'short'. I am maybe really tired today but I cannot see the issue!

John V
  • 4,855
  • 15
  • 39
  • 63

3 Answers3

32

And it does not compile, saynig cannot convert 'int' to 'short'. I am maybe really tired today but I cannot see the issue!

It's just the way the language is defined. The + operator on integer types is defined for:

static uint op +(uint x, uint y)
static int op +(int x, int y)
static ulong op +(ulong x, ulong y)
static long op +(long x, long y)

Operands are promoted as required.

Now as for the reasons why it's defined that way - I don't know, to be honest. I don't buy the argument of "because it could overflow" - that would suggest that byte + byte should be defined to return short, and that int + int should return long, neither of which is true.

I've heard somewhere that it could be performance related, but I wouldn't like to say for sure. (Perhaps processors typically only provide integer operations on 32 and 64 bit integers?)

Either way, it doesn't really matter why it's the case - it's just the rules of the language.

Note that the compound assignment operators have an implicit conversion back to the relevant type, so you can write:

short x = 10;
short y = 20;
x += y;
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks, so even whem I want to use as little memory as possible, I just have to use ints here? – John V Aug 07 '12 at 20:33
  • @user970696: Nope, you can cast: `return (short) a + b;`. But I'd be wary of micro-optimizing... – Jon Skeet Aug 07 '12 at 20:33
  • 1
    @JonSkeet That won't compile either (order of operations). You need to wrap the addition in parens. – Servy Aug 07 '12 at 20:34
  • 1
    Jon - in my defence: http://stackoverflow.com/a/4347752/1583 – Oded Aug 07 '12 at 20:34
  • 4
    @Oded: Fair enough, but in this case it still feels like a weak argument *even though that means disagreeing with Eric*. I'll get my coat. – Jon Skeet Aug 07 '12 at 20:35
  • x86 has instruction for 16bit math, but they're problematic. (slow decoding in some circumstances, and lots of false dependencies) – harold Aug 07 '12 at 20:38
  • @harold: Right - so does performance make sense as a reason? – Jon Skeet Aug 07 '12 at 21:04
  • @JonSkeet (sorry about the delay), well not too much really, they could have implemented 16 bit math on top of 32 bit math (which is what they already do anyway) but throw away the top half in the right places (before right shifts, divisions and modulo is about all, I think). That wouldn't really have hurt performance. – harold Aug 08 '12 at 06:49
  • Old days: "s1 += s2" meant "s1 = s1 + s2" (16-bit addition). Now, "+" doesn't support short. The compiler never uses any 16-bit or 8-bit add and subtract instructions, even if you want it to. (Is that crazy?) (Increment ++ and decrement -- too?) The compiler promotes the operands to int and then demotes the result to short. Now, "s1 += s2" implies "s1 = (short)( (int)s1 + (int)s2 )". Now, if you say "s1 = s1 + s2", you imply "s1 = (int)s1 + (int)s2", which is illegal. You have to say "s1 = (short)(s1 + s2)". – A876 Aug 01 '17 at 19:53
  • In case anyone still wonders, this is explained in detail here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#addition-operator – Don Box Oct 22 '19 at 10:33
9

When you add two shorts together, they can add up to more than the allowed value of a short, but an OK value for an int. This is pretty much what Eric Lippert says in his answer here.


Aside: Why is that not the case for adding two ints returning a long? Eric addresses that too:

In a world where integer arithmetic wraps around it is much more sensible to do all the calculations in int, a type which is likely to have enough range for typical calculations to not overflow.


Because of that, the + operator defined on adding two shorts returns an int.

This is why you are getting the compile time error - you are returning an int where you are specifying a short return type`.

You can explicitly cast the result to short if you know that the addition will always result in a short:

static short Sum(short a, short b)
{
    return (short)(a + b);
}
Community
  • 1
  • 1
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • 2
    That's an argument for not letting you sum two `int` values to get another `int`. – Jon Skeet Aug 07 '12 at 20:27
  • Yes they can, but does not have to. I can do that with ints and expect a long.. – John V Aug 07 '12 at 20:28
  • 2
    @JonSkeet Ah, but the chances of that happening are only half as big. – Mr Lister Aug 07 '12 at 20:28
  • @user970696: You can expect it, but you'll be disappointed. If you add `int.MaxValue` and `1`, you won't get a `long` value which is bigger than `int.MaxValue` - you'll get `int.MinValue`. – Jon Skeet Aug 07 '12 at 20:30
  • @user970696 - True, but than't not how the language works. The designers decided to allow `int`s to overflow, but not `short`s. – Oded Aug 07 '12 at 20:36
0

Jon Skeet has explained in detail why your code doesn't work, but he hasn't listed what you need to do in order for it to compile. You can use the following:

static short Sum(short a, short b)
{
    return (short)(a + b);
}
Community
  • 1
  • 1
Servy
  • 202,030
  • 26
  • 332
  • 449
  • That is okay, I was looking for a way how to simply cause overflow oexception ;) – John V Aug 07 '12 at 20:34
  • You should take situations into account where `short x` + `short y` exceeds the maximum value for a short; make it throw an exception. @user970696 the simplest way to cause an overflow exception would be just to `throw new OverflowException();` – aevitas Aug 07 '12 at 20:34
  • @aevitas That depends on whether or not throwing an exception is desirable. In either case, you should use either a `checked` or `unchecked` block around the code to get the desired behavior rather than manually checking and throwing the exception. – Servy Aug 07 '12 at 20:36
  • Well I was looking how to make C# naturaly cause that exception without forcing it from using inbuilt mechanisms. – John V Aug 07 '12 at 20:39
  • @user970696 - For that you can use the [`checked`](http://msdn.microsoft.com/en-us/library/74b4xzyw.aspx) keyword. – Oded Aug 07 '12 at 20:39
  • 1
    Yes, `return checked((short)(x + y));`. – Jeppe Stig Nielsen Aug 07 '12 at 21:59