No puedo darte el razonamiento, pero puedo decir por qué el compilador tiene ese comportamiento desde el punto de vista de las reglas que el compilador debe seguir (lo que realmente no es lo que te interesa saber).
De una vieja copia de la especificación C# (probablemente debería descargar una versión más reciente), énfasis añadido:
14.2.6.2 Binary numeric promotions This clause is informative.
Binary numeric promotion occurs for the operands of the predefined +
, ?
, *
, /
, %
, &
, |
, ^
, ==
, !=
, >
, <
, >=
, and <=
binary operators. Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric promotion consists of applying the following rules, in the order they appear here:
- If either operand is of type decimal, the other operand is converted to type decimal, or a compile-time error occurs if the other operand is of type float or double.
- Otherwise, if either operand is of type double, the other operand is converted to type double.
- Otherwise, if either operand is of type float, the other operand is converted to type float.
- Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a compile-time error occurs if the other operand is of type sbyte, short, int, or long.
- Otherwise, if either operand is of type long, the other operand is converted to type long.
- Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
- Otherwise, if either operand is of type uint, the other operand is converted to type uint.
- Otherwise, both operands are converted to type int.
Así que, básicamente operandos más pequeño que un int
se convertirá en int
para estos operadores (y el resultado será un int
para las operaciones no relacionales).
Dije que no podía darle un razonamiento; sin embargo, adivinaré uno: creo que los diseñadores de C# querían asegurarse de que las operaciones que podrían perder información si se redujeran necesitarían tener esa operación de reducción explícita por el programador en forma de un reparto. Por ejemplo:
byte a = 200;
byte b = 100;
byte c = a + b; // value would be truncated
Si bien este tipo de truncamiento no ocurriría cuando se realiza una operación XOR entre dos operandos de byte, creo que los diseñadores del lenguaje probablemente no quiere tener un conjunto más complejo de reglas, donde algunos las operaciones necesitarían moldes explícitos y otras no.
Sólo una pequeña nota: la cita anterior es 'informativo' no 'normativo', pero cubre todos los casos en una forma fácil de leer. En sentido estricto (en un sentido normativo), la razón por la que el operador ^
se comporta de esta manera es porque la sobrecarga más cercano para que el operador cuando se trata de byte
operandos está (de 14.10.1 "operadores lógicos entero"):
int operator ^(int x, int y);
Por lo tanto, como explica el texto informativo, los operandos se promocionan a int
y se produce un resultado int
.
de hecho es extraño, las operaciones a nivel de bits (bueno, excepto para cambiar a la izquierda) no se desbordan – Hao
operaciones de bytes en general pueden devolver valores mayores que 255, como cuando dejó un byte, por supuesto y/o los operadores no lo hacen generar resultados más grandes que byte, pero por el bien de la compatibilidad, el resultado será int! –