2008-09-04 13 views
19

Я следующий C# код:C# числовые константы

byte rule = 0; 
... 
rule = rule | 0x80; 

который производит ошибку:

Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)

[Update: первая версия этого вопроса была неправильно ... Я неправильно интерпретировал вывод компилятора ]

Добавление бросание не решить эту проблему:

rule = rule | (byte) 0x80; 

мне нужно написать:

rule |= 0x80; 

Который только кажется странным. Почему оператор |= отличается от оператора |?

Есть ли другой способ сообщить компилятору относиться к константе как к байту?


@ Джованни Galbo: да и нет. Код относится к программированию флэш-памяти во внешнем устройстве и логически представляет один байт памяти. Я мог бы наложить его позже, но это показалось более очевидным. Наверное, мое наследие C проявляется слишком много!

@ Джонатон Holland: свойство «как» синтаксис выглядит аккуратнее, но, к сожалению, похоже, не работает ... он производит:

The as operator must be used with a reference type or nullable type ('byte' is a non-nullable value type)

ответ

6
int rule = 0; 
rule |= 0x80; 

http://msdn.microsoft.com/en-us/library/kxszd0kx.aspx The | оператор определен для всех типов значений. Я думаю, что это приведет к намеченному результату. Оператор «| =» является или присваивает оператор, который является просто сокращением для правила = правило | 0x80.

Один из самых простых вещей о C# заключается в том, что он позволяет вам делать сумасшедшие вещи, такие как типы ценностей злоупотребления, просто основанные на их размере. «Int» точно совпадает с байтом, за исключением того, что компилятор будет вызывать предупреждения, если вы попытаетесь использовать их как в одно и то же время. Просто придерживаться одного (в данном случае, int) работает хорошо. Если вас беспокоит 64-разрядная готовность, вы можете указать int32, но все int - int32, даже работающие в режиме x64.

+0

Как вы говорите, все ints - int32, не указывает ли спецификация языка (или CLR) эту гарантию? – Eloff 2010-05-04 22:59:09

34

C# не имеет буквального суффикса для байта. u = uint, l = long, ul = ulong, f = float, m = decimal, но не байт. Вы должны бросить его.

+2

Как это произошло? – User 2009-06-21 17:51:00

+2

пользователь: он не определен в спецификации языка C#. Там пример здесь: http://msdn.microsoft.com/en-us/library/5bdb6693(VS.80).aspx Вы можете объявить и инициализировать переменные байты как в этом примере: байты myByte = 255 ; В предыдущем объявлении целочисленный литерал 255 неявно преобразован из int в байт. Если целочисленный литерал превышает диапазон байтов, произойдет ошибка компиляции. – blizpasta 2010-08-20 02:09:15

9

Термин, который вы ищете, является «Literal», и, к сожалению, C# не имеет байтового литерала.

Вот список all C# literals.

3

В соответствии с ECMA Specification, pg 72 нет байтового литерала. Только целые литералы для типов: int, uint, long и ulong.

0

К сожалению, ваше единственное средство - это сделать так, как вы. Суффикса для обозначения литерала как байта нет. | оператор не предусматривает неявное преобразование как назначение (то есть инициализация).

11

Это работает:

rule = (byte)(rule | 0x80); 

Видимо выражение «правила | 0x80 'возвращает int, даже если вы определяете 0x80 как' const byte 0x80 '.

0

Apparently the expression 'rule | 0x80' returns an int even if you define 0x80 as 'const byte 0x80'.

Я думаю, что правило - это числа, такие как 0x80 по умолчанию для int, если вы не включили литеральный суффикс. Таким образом, для выражения rule | 0x80 результатом будет int, так как 0x80 является int и правило (которое является байтом) можно безопасно преобразовать в int.

0

Согласно стандарту C байты ВСЕГДА продвигают к int в выражениях, даже константах. Однако до тех пор, пока оба значения НЕ ПОДКЛЮЧАЮТСЯ, старшие биты будут отброшены, поэтому операция должна вернуть правильное значение.

Аналогично, поплавки способствуют удваивать и т.д.

вытаскивать из копии K & R. Это все там.

1

Почти пять лет спустя, и никто на самом деле не ответил на вопрос.

Несколько ответов утверждают, что проблема заключается в отсутствии байтового литерала, но это не имеет значения. Если вы исчислите (byte1 | byte2), значит, сумма была произведена int. Даже если «b» был буквальным суффиксом для байта, тип (23b | 32b) все равно будет int.

Подходящий ответ ссылается на статью MSDN, в которой утверждается, что operator| определен для всех интегральных типов, но это также неверно.

operator| не указан на byte, поэтому компилятор использует свои обычные правила разрешения перегрузки, чтобы выбрать версию, определенную на int. Поэтому, если вы хотите, чтобы присвоить результат к byte вам нужно бросить его:

rule = (byte)(rule | 0x80); 

остается вопрос, почему rule |= 0x80; работу?

Поскольку спецификация C# имеет специальное правило для составного назначения, которое позволяет опустить явное преобразование. В составном присвоении x op= y правило составляет:

if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y) , where T is the type of x, except that x is evaluated only once.