Подтвердить что ты не робот

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

Если у меня есть два byte a и b, как получится:

byte c = a & b;

выдает ошибку компилятора о литье байта в int? Он делает это, даже если я поставлю явное выражение перед a и b.

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

4b9b3361

Ответ 1

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

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

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

Тип возврата не int, если один или оба аргумента long, ulong или uint.


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

Результат byte & byte - это int, потому что в байте нет оператора &. (Источник)

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

Ответ 2

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

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

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


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

Ответ 3

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

  • ИНТ
  • UINT
  • длинный
  • ULONG
  • поплавок
  • двойной
  • десятичное

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

Все это в спецификациях С# версии 5.0 (раздел 7.3.6.2):

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

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

Ответ 4

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