Если я имею два byte
s a
и b
, каким образом:
byte c = a & b;
производит ошибку компилятора о кастинге байта к интервалу? Это делает это, даже если я поместил явный бросок перед a
и b
.
Кроме того, я знаю об этом вопросе, но я действительно не знаю, как он применяется здесь. Это кажется, что это - вопрос типа возврата operator &(byte operand, byte operand2)
, в котором компилятор должен смочь разобраться точно так же, как любой другой оператор.
Почему побитовые операторы 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
.
Такое поведение является следствием дизайна 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
Я написал более обширный пост об этом здесь.
Бинарные операторы не определены для байтовых типов (среди прочих). Фактически, все двоичные (числовые) операторы действуют только со следующими собственными типами:
Если задействованы какие-либо другие типы, он будет использовать один из вышеперечисленных.
Это все в спецификации C # версии 5.0 (раздел 7.3.6.2) :
Двоичное числовое преобразование происходит для операндов предопределенных +, -, *, /,%, &, |, ^, ==,! =,>, <,> = и <= бинарные операторы. Двоичное числовое продвижение неявно преобразует оба операнда в общий тип, который в случае нереляционных операторов также становится типом результата операции. Двоичное числовое продвижение состоит из применения следующих правил в том порядке, в котором они появляются здесь:
Это потому, что & определено для целых чисел, а не для байтов, и компилятор неявно приводит ваши два аргумента к int.