2010-09-04 84 views

回答

29

令人惊讶的是,当您对字节执行操作时,计算将使用int值完成,其中字节首先隐式转换为(int)。对于short s也是如此,并且在执行浮点算术时,float s同样被上转换为double

第二个片段是等价于:

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

因此必须把结果返回到(byte),让编译器承担的任务。

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

有人可以验证类型转换是否发生在someVar- = 3的IL级别;例?它是否生成相同的IL代码? – Dested 2010-09-04 07:29:23

+2

我刚刚检查了反射器。 ' - ='运算符在IL级别生成'conv.u1',这就是为什么第一个代码段正在工作的原因 – 2010-09-04 13:51:00

+5

@Dested精确的规则在C#语言规范中给出。它规定:_“上面的第二个规则允许'x op = y'在某些上下文中被评估为'x =(T)(x op y)'。规则的存在使得预定义的操作符可以用作复合操作符当左操作数是'sbyte','byte','short','ushort'或'char'类型时,即使两个参数都是这些类型之一,预定义的运算符也会产生类型为“int” ,如第7.3.6.2节所述,因此,如果没有强制转换,则不能将结果赋给左操作数。“_ – 2013-01-04 12:35:10

11

这里的一个表中的CLI规范(ECMA 335)指定哪些操作数上的类型A的运算B,其中A和B是操作数和“OP”的二进制数值运算符有效副本是运营商,像Opcodes.Sub您正在使用您的片段:

alt text

一些注释需要用这样的:

  • “原生INT” 是在的IntPtr C#程序
  • ˚F表示浮点型,双或漂浮在C#
  • &表示的指针值,所述框被阴影,因为它们是不安全的操作
  • ö表示一个对象引用
  • x是不允许的操作。

注意事项˚F的行和列,两个操作数必须浮点,你不能直接添加,即int的两倍。 C#编译器通过自动将int操作数转换为double来处理该限制,以便操作符有效。

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

现在,这里是擦:结果是int32,但将它分配给一个字节值需要一个缩小转换。从32位到8位。这很麻烦,因为它失去了重要的位。 C#编译器要求您明确说明。你基本上承认你知道你在做什么,并且你意识到了可能出人意料的结果。像这样:

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

- =操作符是一个问题,因为没有有效的方法来应用所需的强制转换。它在语言语法中不可表达。使用(字节)3没有意义,文字无论如何都转换为int32以使操作符工作。

他们解决了这个问题,编译器会自动发出投射而无需您的帮助。

+0

这解释了为什么我无法使用反射来在类型之间隐式转换。 – fusi 2015-09-03 13:18:05