Почему я могу передать 1 как короткую, но не переменную int i?

Почему первая и вторая записи работают, но не последние? Есть ли способ, которым я могу разрешить все 3 из них и определить, было ли это 1, (int) 1 или я прошел? И действительно, почему разрешено, но последнее? Вторая возможность, но не последняя, ​​действительно ударит меня.

Демоверсия для компиляции

using System;
class Program
{
    public static void Write(short v) { }
    static void Main(string[] args)
    {
        Write(1);//ok
        Write((int)1);//ok
        int i=1;
        Write(i);//error!?
    }
}

Ответ 1

Первые два являются постоянными выражениями, последний - нет.

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

Это правило соответствует директиве о том, что неявные преобразования должны быть без потерь.

6.1.8. Неявные преобразования константных выражений

Неявное преобразование константных выражений допускает следующие преобразования:

  • Константное выражение (§7.18) типа int может быть преобразовано в тип sbyte, byte, short, ushort, uint или ulong, если значение константное выражение находится в пределах диапазона типа назначения.
  • Константное выражение типа long может быть преобразовано в тип ulong, если значение константного выражения не является отрицательным.

(Цитируется по языковой версии С# версии 3.0)

Ответ 2

Нет никакого неявного преобразования от int до short из-за возможности усечения. Однако константное выражение может быть обработано компилятором как целевой тип.

1? Не проблема: это явно действительное значение short. i? Не так много - например, может быть какое-то значение > short.MaxValue, и компилятор не может проверить это в общем случае.

Ответ 3

an int литерал может быть неявно преобразован в short. Принимая во внимание:

Вы не можете неявно конвертировать нелитературные числовые типы большего размера хранилища в короткий

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

Ответ 4

Я считаю, что это потому, что вы передаете литерал/константу в первых двух, но нет автоматического преобразования типов при передаче в целое число в третьем.

Изменить: Кто-то избил меня до этого!

Ответ 5

Потому что не будет никакого неявного преобразования между типом Nonliteral и short size.

Неявное преобразование возможно только для константного выражения.

public static void Write(short v) { }

Если вы передаете значение integer в качестве аргумента short

int i=1;
Write(i);  //Which is Nonliteral here

Ответ 6

Компилятор сказал вам, почему код не работает:

cannot convert `int' expression to type `short'

Итак, вот вопрос, на который вы должны спросить: почему это преобразование терпит неудачу? Я googled "С# convert int short" и попал на страницу MS С# для ключевого слова short:

http://msdn.microsoft.com/en-us/library/ybs77ex4(v=vs.71).aspx

Как говорится на этой странице, неявные отбрасывания от более крупного типа данных до short допускаются только для литералов. Компилятор может сказать, когда литерал выходит за пределы допустимого диапазона, но не в противном случае, поэтому требуется подтверждение того, что вы избежали ошибки вне диапазона в вашей логике программы. Это заверение обеспечивается литой.

Write((short)i)

Ответ 7

Преобразование из int → short может привести к усечению данных. Вот почему.