C#int字节转换

C#int字节转换,c#,int,byte,C#,Int,Byte,为什么 有效但 byte someVar; someVar -= 3; isnt?令人惊讶的是,当您对字节执行操作时,将使用int值进行计算,首先将字节隐式转换为(int)。这同样适用于shorts,类似地,在执行浮点运算时,floats被上转换为double 第二个代码段相当于: byte someVar; someVar = someVar - 3; 因此,必须将结果强制转换回(byte),以使编译器接受赋值 byte someVar; someVar = (int) someVar

为什么

有效但

byte someVar;
someVar -= 3; 

isnt?

令人惊讶的是,当您对字节执行操作时,将使用
int
值进行计算,首先将字节隐式转换为
(int)
。这同样适用于
short
s,类似地,在执行浮点运算时,
float
s被上转换为
double

第二个代码段相当于:

byte someVar;
someVar = someVar - 3;
因此,必须将结果强制转换回
(byte)
,以使编译器接受赋值

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

以下是CLI规范(Ecma 335)中的一个表的副本,该表指定了哪些操作数对a op B类型的二进制数字运算符有效,其中a和B是操作数,“op”是运算符,如代码段中使用的操作码。Sub:

这需要一些注释:

  • “native int”是C#程序中的IntPtr
  • F表示浮点类型,在C中为double或float#
  • &表示一个指针值,框被着色,因为它们是不安全的操作
  • O表示对象引用
  • x是不允许的操作
请注意F的行和列,两个操作数都必须是浮点,不能直接将int添加到double中。C#编译器通过自动将int操作数转换为double来处理该限制,从而使运算符有效

与您的问题相关:还要注意,byte、sbyte、char、short和ushort类型不存在。同样,编译器将操作数转换为可以表示值的最小类型,以便使用运算符。这将是int32。根据该表,该操作的结果将为int32

现在问题来了:结果是int32,但将其赋值回字节值需要进行窄化转换。从32位到8位。这很麻烦,因为它会丢失重要的位。C#编译器要求您将其显式化。你基本上承认你知道你在做什么,并且你知道潜在的令人惊讶的结果。像这个:

someVar = (byte) (someVar - 3);
-=运算符是一个问题,因为没有有效的方法应用所需的强制转换。它不能用语言语法表达。使用(字节)3是没有意义的,不管怎样,文本都会转换为int32以使运算符工作


他们解决了这个问题,编译器在没有您帮助的情况下自动发出转换。

有人能验证类型转换是否发生在someVar-=3中的IL级别;例子?它是否生成相同的IL代码?我刚和Reflector检查过。
-=
运算符在IL级别生成一个
conv.u1
,这就是为什么第一个代码段是working@DestedC语言规范中给出了精确的规则。它指出:“上面的第二条规则允许
xop=y
被评估为
x=(T)(xopy)
在某些上下文中。当左操作数的类型为
sbyte
byte
short
ushort
char
时,该规则的存在使得预定义运算符可以用作复合运算符。即使这两个参数都属于其中一种类型,预定义运算符也会生成一个类型的结果e
int
,如§7.3.6.2所述。因此,如果没有强制转换,将无法将结果分配给左操作数。“这解释了为什么我无法使用反射在类型之间隐式强制转换。
byte v = 255;
v = (byte)(v + 1);