2010-09-04 21 views

Respuesta

29

Sorprendentemente, cuando realiza operaciones en bytes los cálculos se realizarán utilizando los valores int, con los bytes implícitamente convertidos a (int) primero. Esto también se aplica a short s, y de forma similar float s se convierten a double al hacer aritmética de coma flotante.

El segundo fragmento es equivalente a:

byte someVar; 
someVar = (int) someVar - 3; 

Debido a esto se debe convertir el resultado a (byte) para obtener el compilador para aceptar la asignación.

someVar = (byte) (someVar - 3); 
+0

¿Alguien puede verificar si el tipo de fundido ocurre en el nivel IL en el someVar- = 3; ¿ejemplo? ¿Genera el mismo código IL? – Dested

+2

Acabo de consultar con Reflector. El operador '- =' genera un 'conv.u1' en el nivel IL, por lo que el primer fragmento está funcionando –

+5

@Dested Las reglas precisas se dan en la Especificación del lenguaje C#. Establece: _ "La segunda regla anterior permite que' x op = y' se evalúe como 'x = (T) (x op y)' en ciertos contextos. La regla existe de tal manera que los operadores predefinidos se pueden usar como operadores compuestos cuando el operando de la izquierda es de tipo 'sbyte',' byte', 'short',' ushort', o 'char'. Incluso cuando ambos argumentos son de uno de esos tipos, los operadores predefinidos producen un resultado de tipo' int' , como se describe en §7.3.6.2. Por lo tanto, sin un molde no sería posible asignar el resultado al operando izquierdo. "_ –

11

Aquí es una copia de una tabla en la especificación CLI (ECMA 335) que especifica qué operandos son validos para los binarios operadores numéricos del tipo A op B, donde A y B son los operandos y "OP" es el operador, como Opcodes.Sub que está utilizando en su fragmento:

alt text

Algunas anotaciones se requieren con esto:

  • "int nativo" es IntPtr en un programa C#
  • F representa un tipo de coma flotante, doble o flotar en C#
  • & representa un valor de puntero, las cajas están sombreados porque son operaciones peligrosas
  • O representa una referencia de objeto
  • x es una operación que no está permitida.

Nota la fila y columna para F, ambos operadores deben de punto flotante, no se puede añadir directamente, por ejemplo, un int a un doble. El compilador de C# se ocupa de esa limitación convirtiendo automáticamente el operando int en el doble para que el operador sea válido.

Pertinente a su pregunta: también tenga en cuenta que los tipos byte, sbyte, char, short y ushort no están presentes. El mismo enfoque, el compilador convierte los operandos al tipo más pequeño que puede representar el valor para que el operador pueda ser utilizado. Que será int32. Según la tabla, el resultado de la operación será int32.

Ahora aquí está el problema: el resultado es int32, pero la asignación de ese valor a un byte requiere una reducción de la conversión. De 32 bits a 8 bits. Eso es un problema porque pierde bits significativos. El compilador de C# requiere que lo hagas explícito. Básicamente, reconoces que sabes lo que estás haciendo y que eres consciente del resultado potencialmente sorprendente.Como este:

byte v = 255; 
v = (byte)(v + 1); 

El operador = = es un problema porque no hay una forma efectiva de aplicar ese tipo de conversión. No es expresable en la sintaxis del lenguaje. El uso (byte) 3 no tiene sentido, el literal se convierte a int32 de todos modos para que el operador funcione.

Respondieron el problema, el compilador emite automáticamente el reparto sin su ayuda.

+0

esto explica por qué no puedo usar la reflexión para emitir implícitamente entre los tipos. – fusi