2008-09-04 21 views
19

Tengo el siguiente código C#:C# numérica constantes de

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

que produce el error:

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

[Actualización: primera versión de la pregunta fue mal ... Me leído mal la salida del compilador ]

adición al elenco no significa soluciona el problema:

rule = rule | (byte) 0x80; 

tengo que escribir como:

rule |= 0x80; 

Lo cual parece raro. ¿Por qué el operador |= es diferente al operador |?

¿Hay alguna otra manera de decirle al compilador que trate la constante como un byte?


@ Giovanni Galbo: sí y no. El código trata de la programación de la memoria flash en un dispositivo externo y, lógicamente, representa un solo byte de memoria. Podría lanzarlo más tarde, pero esto parecía más obvio. ¡Creo que mi herencia de C se muestra demasiado!

@ Jonathon Holanda: el 'como' sintaxis es más limpio, pero por desgracia no parece funcionar ... Produce:

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

Respuesta

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

http://msdn.microsoft.com/en-us/library/kxszd0kx.aspx The | operador se define para todos los tipos de valores. Creo que esto producirá el resultado deseado. El operador "| =" es un operador o luego asigna, que es simplemente una abreviatura de regla = regla | 0x80.

Una de las cosas más nuevas sobre C# es que te permite hacer cosas locas como tipos de valor de abuso simplemente en función de su tamaño. Un 'int' es exactamente lo mismo que un byte, excepto que el compilador lanzará advertencias si lo intenta y las usa como ambas al mismo tiempo. Simplemente quedarse con uno (en este caso, int) funciona bien. Si le preocupa la preparación de 64 bits, puede especificar int32, pero todas las entradas son int32s, incluso se ejecutan en modo x64.

+0

Como dices, todas las entradas son int32, ¿la especificación del lenguaje (o CLR) no garantiza esta garantía? – Eloff

+4

int es un alias de C# para Int32 y definitivamente no es lo mismo que un byte. El compilador JIT es consciente de la plataforma, por lo que no es necesario. Es más probable que el tamaño de la palabra nativa, el direccionamiento y la eficacia de las operaciones frente a varias primitivas nativas se relacionen con la forma en que asigna los datos gestionados (incluidas las "primitivas") en el sistema subyacente.Tenga en cuenta que se puede compilar el mismo código para .NET Micro y .NET CF (ARM de orientación para teléfono y PowerPC para XBox 360). Estos sistemas incluso pueden expresar sus números con endianness diferente que tiene efectos importantes en las operaciones binarias. – TheXenocide

34

C# no tiene un sufijo literal para el byte. u = uint, l = largo, ul = ulong, f = flotante, m = decimal, pero no byte. Tienes que lanzarlo.

+2

¿Cómo sucedió? – User

+2

usuario: no está definido como las especificaciones de lenguaje C#. Hay un ejemplo aquí: http://msdn.microsoft.com/en-us/library/5bdb6693(VS.80).aspx Se puede declarar e inicializar una variable de bytes como en este ejemplo: bytes = 255 myByte ; En la declaración anterior, el literal entero 255 se convierte implícitamente de int a byte. Si el literal entero excede el rango del byte, se producirá un error de compilación. – blizpasta

9

El término que está buscando es "Literal" y, lamentablemente, C# no tiene un byte literal.

Aquí hay una lista de all C# literals.

0

Lamentablemente, su único recurso es hacerlo de la manera que usted tiene. No hay sufijo para marcar el literal como un byte. El | el operador no proporciona la conversión implícita como lo haría una asignación (es decir, la inicialización).

11

Esto funciona:

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

Al parecer, la expresión 'regla | 0x80 'devuelve un int incluso si define 0x80 como' const byte 0x80 '.

0

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

Creo que la regla es números como 0x80 por defecto a int a menos que incluya un sufijo literal. Por lo tanto, para la expresión rule | 0x80, el resultado será un int ya que 0x80 es una int y la regla (que es un byte) se puede convertir de forma segura a int.

+0

Esto es incorrecto. Incluso si lanzas 0x80 a un byte, el operador '|' te da un int. Pruebe: 'rule = rule | (byte) 0x80; 'para ver a qué me refiero. Sin embargo, puede envolver toda la operación entre paréntesis y convertirla en byte: 'rule = (byte) (rule | 0x80);' – Ethan

0

De acuerdo con el estándar C, los bytes SIEMPRE promueven a int en expresiones, incluso constantes. Sin embargo, mientras ambos valores estén DESIGNADOS, los bits de orden superior se descartarán para que la operación devuelva el valor correcto.

Del mismo modo, los flotadores Promover el doble, etc.

retirarse de copia de K & R. Está todo ahí.

1

Casi cinco años después y nadie ha respondido la pregunta.

Un par de respuestas afirman que el problema es la falta de un byte literal, pero esto es irrelevante. Si calcula (byte1 | byte2) el resultado es del tipo int. Incluso si "b" fuera un sufijo literal para byte, el tipo de (23b | 32b) seguiría siendo int.

La respuesta aceptada enlaza con un artículo de MSDN que afirma que operator| se define para todos los tipos integrales, pero esto tampoco es cierto.

operator| no está definido en byte por lo que el compilador usa sus reglas de resolución de sobrecarga habituales para elegir la versión que está definida en int. Por lo tanto, si desea asignar el resultado a un byte que necesita para su emisión:

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

La pregunta sigue siendo, ¿por qué rule |= 0x80; trabajo?

Porque la especificación C# tiene una regla especial para la asignación compuesta que le permite omitir la conversión explícita. En la asignación compuesta x op= y, la regla es:

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.