Pregunta

Tengo el siguiente código C#:

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

lo que produce el error:

No se puede convertir implícitamente el tipo 'int' a 'byte'.Existe una conversión explícita (¿te falta una conversión?)

[Actualizar:La primera versión de la pregunta estaba equivocada...Leí mal la salida del compilador]

Agregando el elenco no arreglar el problema:

rule = rule | (byte) 0x80;

Necesito escribirlo como:

rule |= 0x80;

Lo cual simplemente parece extraño.Porque es el |= operador diferente al | ¿operador?

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


@Giovanni Galbo :si 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.¡Supongo que mi herencia C se está mostrando demasiado!

@ Jonathon Holanda :la sintaxis 'as' parece más clara pero desafortunadamente no parece funcionar...produce:

El operador as debe usarse con un tipo de referencia o un tipo que acepta valores NULL ('byte' es un tipo de valor que no admite NULL)

¿Fue útil?

Solución

int rule = 0;
rule |= 0x80;

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

Una de las cosas más ingeniosas de C# es que te permite hacer cosas locas como abusar de los tipos de valores simplemente en función de su tamaño.Un 'int' es exactamente lo mismo que un byte, excepto que el compilador generará advertencias si intenta usarlos como ambos al mismo tiempo.Simplemente seguir con uno (en este caso, int) funciona bien.Si le preocupa la preparación de 64 bits, puede especificar int32, pero todos los ints son int32, incluso ejecutándose en modo x64.

Otros consejos

C# no tiene un sufijo literal para byte.u = uint, l = long, ul = ulong, f = float, m = decimal, pero sin bytes.Tienes que lanzarlo.

Esto funciona:

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

Aparentemente la regla de la expresión | 0x80 'Devuelve un int incluso si define 0x80 como' const byte 0x80 '.

El término que busca es "Literal" y desafortunadamente C# no tiene un byte literal.

Aquí hay una lista de todos los literales de C#.

De acuerdo con la Especificación ECMA, página 72 no hay ningún byte literal.Sólo literales enteros para los tipos:int, uint, largo y ulong.

Parece que quizás tengas que hacerlo de la manera fea: http://msdn.microsoft.com/en-us/library/5bdb6693.aspx.

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

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

La respuesta aceptada enlaza a un artículo de MSDN que afirma que operator| está definido para todos los tipos integrales, pero esto tampoco es cierto.

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

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

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

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 tarea compuesta x op= y la regla es:

si el operador seleccionado es un operador predefinido, si el tipo de retorno del operador seleccionado es explícitamente convertible al tipo de x, y si y es implícitamente convertible al tipo de x o el operador es un operador de desplazamiento, entonces se evalúa la operación como x = (T)(x op y), donde T es el tipo de x, excepto que x se evalúa solo una vez.

Desafortunadamente, su único recurso es hacerlo tal como lo ha hecho.No hay ningún sufijo para marcar el literal como un byte.El | El operador no proporciona la conversión implícita como una tarea (es decir,inicialización) lo haría.

Aparentemente la regla de la expresión | 0x80 'Devuelve un int incluso si define 0x80 como' const byte 0x80 '.

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

Según el estándar C, los bytes SIEMPRE ascienden a int en expresiones, incluso en constantes.Sin embargo, siempre que ambos valores estén SIN FIRMAR, los bits de orden superior se descartarán por lo que la operación debería devolver el valor correcto.

De manera similar, los flotadores ascienden al doble, etc.

Saque de una copia de K&R.Está todo ahí dentro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top