Вопрос
У меня есть следующий код на C #:
byte rule = 0;
...
rule = rule | 0x80;
который выдает ошибку:
Не удается неявно преобразовать тип 'int' в 'byte'.Существует явное преобразование (вам не хватает приведения?)
[Обновить:первая версия вопроса была неверной ...Я неправильно истолковал вывод компилятора]
Добавление приведенного состава не делает устраните проблему:
rule = rule | (byte) 0x80;
Мне нужно написать это следующим образом:
rule |= 0x80;
Что просто кажется странным.Почему это происходит |=
оператор, чем-либо отличающийся от |
оператор?
Есть ли какой-либо другой способ сообщить компилятору, чтобы он обрабатывал константу как байт?
@ Giovanni Galbo :и да, и нет.Код имеет дело с программированием флэш-памяти во внешнем устройстве и логически представляет собой один байт памяти.Я мог бы разыграть его позже, но это казалось более очевидным.Я думаю, мое наследие Си слишком сильно проявляется!
@ Джонатан Холланд :синтаксис 'as' выглядит аккуратнее, но, к сожалению, похоже, что он не работает ...это производит:
Оператор as должен использоваться со ссылочным типом или типом с нулевым значением ('byte' - это ненулевой тип значения).
Решение
int rule = 0;
rule |= 0x80;
http://msdn.microsoft.com/en-us/library/kxszd0kx.aspx Оператор | определен для всех типов значений.Я думаю, что это приведет к желаемому результату.Оператор "|=" - это оператор or then assign , который является просто сокращением для rule = rule | 0x80.
Одна из самых замечательных особенностей C # заключается в том, что она позволяет вам делать сумасшедшие вещи, такие как злоупотребление типами значений, просто основываясь на их размере.'Int' - это точно то же самое, что и байт, за исключением того, что компилятор будет выдавать предупреждения, если вы попытаетесь использовать их как оба одновременно.Простое использование одного из них (в данном случае int) работает хорошо.Если вас беспокоит 64-разрядная готовность, вы можете указать int32, но все целые значения являются int32, даже если они работают в режиме x64.
Другие советы
В C # нет буквального суффикса для byte.u = uint, l = long, ul = ulong, f = float, m = десятичная дробь, но без байта.Вы должны разыграть его.
Это работает:
rule = (byte)(rule | 0x80);
Очевидно, что выражение 'rule | 0x80' возвращает значение int, даже если вы определяете 0x80 как 'постоянный байт 0x80'.
Термин, который вы ищете, - "Буквальный", и, к сожалению, в C # нет байтового литерала.
Вот список все литералы C #.
В соответствии с Спецификация ECMA, стр. 72 здесь нет байтового литерала.Только целочисленные литералы для типов:int, uint, длинный и улонг.
Похоже, вам, возможно, просто придется сделать это уродливым способом: http://msdn.microsoft.com/en-us/library/5bdb6693.aspx.
Прошло почти пять лет, а никто так и не ответил на этот вопрос.
В паре ответов утверждается, что проблема заключается в отсутствии байтового литерала, но это не имеет значения.Если вы рассчитаете (byte1 | byte2)
результат имеет вид int
.Даже если бы "b" было буквальным суффиксом для байта, тип (23b | 32b)
все равно было бы int
.
Принятый ответ ссылается на статью MSDN, в которой утверждается, что operator|
определено для всех целых типов, но это также неверно.
operator|
не определено на byte
таким образом, компилятор использует свои обычные правила разрешения перегрузки, чтобы выбрать версию, которая определена на int
.Следовательно, если вы хотите присвоить результат byte
вам нужно разыграть его:
rule = (byte)(rule | 0x80);
Остается вопрос, почему это происходит rule |= 0x80;
работать?
Потому что в спецификации C # есть специальное правило для составного присваивания, которое позволяет вам опустить явное преобразование.В составном задании x op= y
это правило таково:
если выбранный оператор является предопределенным оператором, если возвращаемый тип выбранного оператора явно преобразуется в тип x, и если y неявно преобразуется в тип x или оператор является оператором сдвига, то операция оценивается как
x = (T)(x op y)
, где T - тип x, за исключением того, что x вычисляется только один раз.
К сожалению, ваш единственный выход - сделать это именно так, как у вас есть.Нет суффикса для обозначения литерала как байта.Оператор | не предусматривает неявного преобразования в виде присваивания (т. е.инициализация) была бы.
Очевидно, что выражение 'rule | 0x80' возвращает значение int, даже если вы определяете 0x80 как 'постоянный байт 0x80'.
Я думаю, что правило заключается в том, что числа типа 0x80 по умолчанию имеют значение int, если вы не включаете буквенный суффикс.Итак , для выражения rule | 0x80
, результатом будет значение int, поскольку 0x80 является значением int, а правило (которое является байтом) может быть безопасно преобразовано в значение int.
Согласно стандарту C, байты ВСЕГДА преобразуются в int в выражениях, даже в константах.Однако, пока оба значения БЕЗ ЗНАКА, биты старшего порядка будут отброшены, поэтому операция должна вернуть правильное значение.
Аналогично, значения float увеличиваются в два раза и т.д.
Вытащите копию K & R.Все это есть там.