为什么下面的代码会引发编译时错误:‘无法将类型'int’隐式转换为'byte':
byte a = 25;
byte b = 60;
byte c = a ^ b;
如果我使用算术c运算符,这将是有意义的,因为a+b的结果可能比单个字节中存储的要大。
但是,将其应用于XOR运算符是没有意义的。在这里,XOR是一个永远不会溢出一个字节的按位操作。
在两个操作对象周围使用强制转换有效:
byte c = (byte)(a ^ b);
发布于 2010-04-28 05:44:21
我不能给你理由,但是我可以从编译器必须遵循的规则(这可能不是你真正感兴趣的)的角度来解释为什么编译器会有这样的行为。
从C#规范的旧副本(我可能应该下载更新的版本)中,重点添加了:
14.2.6.2二进制数字促销此子句提供信息。
对预定义的+
、?
、*
、/
、%
、&
、|
、^
、==
、D10、D11、D12、D13和D14二元运算符的操作数进行二进制数值提升。二进制数值提升隐式地将两个操作数转换为公共类型,对于非关系运算符,该类型也成为操作的结果类型。二进制数字升级包括按以下规则在此处出现的顺序应用这些规则:
如果其中一个操作数的类型为decimal,则为
类型
因此,对于这些运算符,小于int
的操作数基本上将被转换为int
(对于非关系操作,结果将是int
)。
我说过我不能给你一个理由;但是,我会猜测一下-我认为C#的设计者想要确保如果缩小可能会丢失信息的操作将需要由程序员以强制转换的形式显式地缩小操作。例如:
byte a = 200;
byte b = 100;
byte c = a + b; // value would be truncated
虽然在两个字节操作数之间执行xor操作时不会发生这种截断,但我认为语言设计者可能不希望有一组更复杂的规则,其中一些操作需要显式强制转换,而另一些则不需要。
注意:上面的引用是“参考”而不是“规范”,但它以一种易于阅读的形式涵盖了所有的案例。严格地说(在标准意义上),^
运算符如此行为的原因是因为在处理byte
操作数时,该运算符的最接近重载是(来自14.10.1“整数逻辑运算符”):
int operator ^(int x, int y);
因此,正如信息性文本所解释的那样,操作数被提升为int
并产生int
结果。
发布于 2010-04-28 05:10:10
来自微软的半神程序员有一个答案:http://blogs.msdn.com/oldnewthing/archive/2004/03/10/87247.aspx
也许它更多的是关于编译器设计的。它们通过泛化编译过程使编译器变得更简单,它不必查看操作数的运算符,因此它将按位运算集中在与算术运算符相同的类别中。因此,经历了类型扩展
链接已死,存档地址:
发布于 2016-10-20 03:59:46
FWIW字节a= 25;字节b= 60;a=a^b;不起作用。然而,字节a= 25;字节b= 60;a ^= b;确实有效。
https://stackoverflow.com/questions/2726920
复制相似问题