С# не позволяет мне суммировать два шорта до короткого

У меня есть код:

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

И он не компилируется, saynig не может преобразовать 'int' в 'short'. Я, может быть, действительно устал сегодня, но я не вижу проблемы!

Ответ 1

И он не компилируется, saynig не может преобразовать 'int' в 'short'. Я, может быть, действительно устал сегодня, но я не вижу проблемы!

Это просто способ определения языка. Оператор + для целых типов определяется для:

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)

Операнды продвигаются по мере необходимости.

Теперь о причинах, почему он определил этот путь - я не знаю, если честно. Я не покупаю аргумент "потому что он может переполняться" - это предполагает, что byte + byte должен быть определен для возврата short и что int + int должен возвращать long, ни одно из которых не является истинным.

Я где-то слышал, что это может быть связано с производительностью, но я не хотел бы говорить точно. (Возможно, процессоры обычно предоставляют только целые операции с 32 и 64-битными целыми числами?)

В любом случае, на самом деле не имеет значения, почему это так - это просто правила языка.

Обратите внимание, что сложные операторы присваивания имеют неявное преобразование обратно к соответствующему типу, поэтому вы можете написать:

short x = 10;
short y = 20;
x += y;

Ответ 2

Когда вы добавляете два шорта вместе, они могут содержать до более допустимого значения короткого, но значение ОК для int. Это в значительной степени то, что Эрик Липперт говорит в его ответе здесь.


Кроме того: почему это не так для добавления двух int, возвращающих long? Эрик тоже обращается к этому:

В мире, где целочисленные арифметические обертывания вокруг него гораздо разумнее выполнять все вычисления в int, тип, который, вероятно, будет иметь достаточный диапазон для типичных вычислений, чтобы не переполняться.


Из-за этого оператор +, определенный при добавлении двух short, возвращает int.

Вот почему вы получаете ошибку времени компиляции - вы возвращаете int, где вы указываете тип возврата short.

Вы можете явно передать результат в short, если знаете, что добавление всегда приведет к short:

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

Ответ 3

Jon Skeet подробно объяснил, почему ваш код не работает, но он не указал, что вам нужно сделать для его компиляции. Вы можете использовать следующее:

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