Почему бинарные операторы C# всегда возвращают интервал независимо от формата их исходных данных?

Если я имею два bytes a и b, каким образом:

byte c = a & b;

производит ошибку компилятора о кастинге байта к интервалу? Это делает это, даже если я поместил явный бросок перед a и b.

Кроме того, я знаю об этом вопросе, но я действительно не знаю, как он применяется здесь. Это кажется, что это - вопрос типа возврата operator &(byte operand, byte operand2), в котором компилятор должен смочь разобраться точно так же, как любой другой оператор.

22
задан Community 23 May 2017 в 11:46
поделиться

4 ответа

Почему побитовые операторы C# всегда возвращают int, независимо от формата их входов?

Не согласен с "всегда". Это работает, и результат a & b имеет тип long:

long a = 0xffffffffffff;
long b = 0xffffffffffff;
long x = a & b;

Возвращаемый тип не является int, если один или оба аргумента являются long, ulong или uint.


Почему побитовые операторы C# возвращают int, если их входные данные - байты?

Результат byte & byte - int, потому что для байта не определен оператор &. (Source)

Оператор & существует для int, а также существует неявное приведение из byte в int. поэтому когда вы пишете byte1 & byte2, это фактически то же самое, что написать ((int)byte1) & ((int)byte2), и результатом этого будет int.

24
ответ дан 29 November 2019 в 04:26
поделиться

Такое поведение является следствием дизайна IL, промежуточного языка, создаваемого всеми компиляторами .NET. Хотя он поддерживает короткие целочисленные типы (byte, sbyte, short, ushort), он имеет лишь очень ограниченное число операций над ними. Загрузка, хранение, преобразование, создание массива - вот и все. Это не случайно, именно такие операции вы могли бы эффективно выполнять на 32-битном процессоре, еще когда IL был разработан, а RISC был будущим.

Операции двоичного сравнения и ветвления работают только с int32, int64, native int, native floating point, object и managed reference. Эти операнды являются 32-битными или 64-битными на любом современном ядре процессора, что гарантирует, что JIT-компилятор может генерировать эффективный машинный код.

Подробнее об этом можно прочитать в Ecma 335, раздел I, глава 12.1 и раздел III, глава 1.5


Я написал более обширный пост об этом здесь.

15
ответ дан 29 November 2019 в 04:26
поделиться

Бинарные операторы не определены для байтовых типов (среди прочих). Фактически, все двоичные (числовые) операторы действуют только со следующими собственными типами:

  • int
  • uint
  • long
  • ulong
  • float
  • double
  • decimal

Если задействованы какие-либо другие типы, он будет использовать один из вышеперечисленных.

Это все в спецификации C # версии 5.0 (раздел 7.3.6.2) :

Двоичное числовое преобразование происходит для операндов предопределенных +, -, *, /,%, &, |, ^, ==,! =,>, <,> = и <= бинарные операторы. Двоичное числовое продвижение неявно преобразует оба операнда в общий тип, который в случае нереляционных операторов также становится типом результата операции. Двоичное числовое продвижение состоит из применения следующих правил в том порядке, в котором они появляются здесь:

  • Если один из операндов имеет тип decimal, другой операнд преобразуется в тип decimal, или возникает ошибка времени компиляции, если другой операнд имеет тип decimal. типа float или double.
  • В противном случае, если один из операндов имеет тип double, другой операнд преобразуется в тип double.
  • В противном случае, если один из операндов имеет тип float, другой операнд преобразуется в тип float.
  • В противном случае, если один из операндов имеет тип ulong, другой операнд преобразуется в тип ulong, или возникает ошибка времени компиляции, если другой операнд имеет тип sbyte, short, int или long.
  • В противном случае, если один из операндов имеет тип long, другой операнд преобразуется в тип long.
  • В противном случае, если один из операндов имеет тип uint, а другой операнд имеет тип sbyte, short или int, оба операнда преобразуются в тип long.
  • В противном случае, если один из операндов имеет тип uint, другой операнд преобразуется в тип uint.
  • В противном случае оба операнда преобразуются в тип int.
5
ответ дан 29 November 2019 в 04:26
поделиться

Это потому, что & определено для целых чисел, а не для байтов, и компилятор неявно приводит ваши два аргумента к int.

2
ответ дан 29 November 2019 в 04:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: