没有强制转换的情况下,两个字节变量的C#XOR将无法编译

时间:2010-04-28 04:57:09

标签: c# operators

为什么以下引发编译时错误:'无法将类型'int'隐式转换为'byte':

        byte a = 25;
        byte b = 60;

        byte c = a ^ b;

如果我使用的是算术运算符,这是有意义的,因为a + b的结果可能大于可以存储在单个字节中的结果。

然而,将此应用于XOR运算符毫无意义。这里是一个按位操作,它永远不会溢出一个字节。

在两个操作数周围使用强制转换:

byte c = (byte)(a ^ b);

8 个答案:

答案 0 :(得分:24)

我不能给你理由,但是我可以告诉为什么编译器从编译器必须遵循的规则的角度来看这种行为(这可能不是你知道的有趣的事情)。 / p>

从C#规范的旧版本(我应该下载更新的版本),重点补充:

  

14.2.6.2二进制数字促销本条款内容丰富。

     

发生二进制数字促销   预定义+?的操作数,   */%&|^==!=,{{ 1}},><>=二元运算符。二进制   数字促销隐式转换   这两种操作数都属于普通类型,   如果是非关系型的   运营商也成为了结果   操作类型。二进制数字   促销包括应用   遵循规则,按顺序排列   出现在这里:

     
      
  • 如果任一操作数的类型为十进制,则另一个操作数为   转换为十进制类型,或者a   如果另一个发生编译时错误   操作数的类型为float或double。
  •   
  • 否则,如果任一操作数的类型为double,则另一个操作数为   转换为double类型。
  •   
  • 否则,如果任一操作数的类型为float,则另一个操作数为   转换为float类型。
  •   
  • 否则,如果任一操作数的类型为ulong,则另一个操作数为   转换为ulong类型,或者a   如果另一个发生编译时错误   操作数的类型为sbyte,short,int,   或者长。
  •   
  • 否则,如果任一操作数的类型为long,则另一个操作数为   转换为long类型。
  •   
  • 否则,如果任一操作数的类型为uint而另一个操作数的类型为   输入sbyte,short或int,两者   操作数转换为long类型。
  •   
  • 否则,如果任一操作数的类型为uint,则另一个操作数为   转换为uint类型。
  •   
  • 否则,两个操作数都将转换为int
  •   

因此,对于这些运算符,基本上小于<=的操作数将转换为int(对于非关系运算,结果将为int

我说我不能给你一个理由;但是,我会猜测一下 - 我认为C#的设计者希望确保在缩小时可能会丢失信息的操作需要让程序员以强制转换的形式明确缩小操作。例如:

int

虽然在两个字节操作数之间执行xor操作时不会发生这种截断,但我认为语言设计者可能不希望有一组更复杂的规则,其中某些操作需要显式转换和其他操作不


只是一个小小的注释:上面的引用是'信息'而不是'规范',但它以易于阅读的形式涵盖了所有案例。严格来说(在规范意义上),byte a = 200; byte b = 100; byte c = a + b; // value would be truncated 运算符以这种方式运行的原因是因为在处理^操作数时该运算符的最近重载是(来自14.10.1“整数逻辑运算符”) :

byte

因此,正如资料性文字所解释的那样,操作数被提升为int operator ^(int x, int y); 并产生int结果。

答案 1 :(得分:2)

微软的半神程序员有一个答案:http://blogs.msdn.com/oldnewthing/archive/2004/03/10/87247.aspx

也许它更多的是编译器设计。它们通过概括编译过程使编译器更简单,它不必查看操作数的运算符,因此它将按位运算与算术运算符集中在同一类别中。因此,进行类型加宽

答案 2 :(得分:1)

我猜它是因为运算符XOR是为布尔值和整数定义的。

从整数结果到字节的结果转换是信息丢失转换;因此需要一个明确的演员阵容(来自程序员的点头)。

答案 3 :(得分:0)

这更多地与CLI规范中隐式和显式转换的规则有关。整数(int = System.Int32 = 4字节)比一个字节宽(显然是1个字节!)。因此,从int到byte的任何转换都可能是一个缩小的转换。因此,编译器希望您明确这一点。

答案 4 :(得分:0)

我以为我记得一个关于此的热门问题。

byte + byte = int... why?

答案 5 :(得分:0)

似乎是因为在C#语言规范中,它被定义为整数和长整数 http://msdn.microsoft.com/en-us/library/aa691307%28v=VS.71%29.aspx

因此,实际发生的是编译器隐式地将字节操作数转换为int,因为这样就不会丢失数据。但是结果(即int)不能在不丢失数据的情况下进行降级(隐式)。所以,你需要明确告诉编译器你知道自己在做什么!

答案 6 :(得分:0)

为什么必须将两个字节转换为整数来执行XOR?

如果您想深入研究,CLI规范(分区I)的12.1.2描述了这样一个事实:在评估堆栈上,只能存在int或long。在评估期间,必须扩展所有较短的整数类型。

不幸的是,我找不到直接与CLI规范的合适链接 - 我有一个本地副本为PDF,但不记得我从哪里得到它。

答案 7 :(得分:-1)

FWIW     字节a = 25;     字节b = 60;     a = a ^ b; 不起作用。然而     字节a = 25;     字节b = 60;     a ^ = b; 确实有效。