有没有人能够解释我这种奇怪的行为?
int i = 0x1234;
byte b1 = (byte)i;
byte b2 = (byte)0x1234; //error: const value '4660' can't convert to byte (use unchecked)
byte b3 = unchecked((byte)0x1234);
byte b4 = checked((byte)i); //throws
byte b5 = (byte)(int)0x1234; //error: same as above
注意:这是一个空的控制台应用程序,启用了 NO 算术检查(默认为)。 提前谢谢大家。
编辑:我应该足够清楚,但不是全部。我知道一个单词不能适合一个字节。但是,默认情况下,C#程序允许某些“危险”操作,主要是出于性能原因。
同样,我可以将两个大整数加在一起,完全没有溢出。
我的疑问是关于上面的编译时错误:编译b1强制转换/赋值,b2无法编译。显然没有区别,因为两者都是Int32具有相同的值。
希望现在很清楚。
答案 0 :(得分:13)
你正在绊倒C#4规范第7.19节的一部分:
除非在
unchecked
上下文中明确放置常量表达式,否则在表达式的编译时评估期间,在整数类型算术运算和转换中发生的溢出总是会导致编译时错误。
基本上,关键是即使你很高兴允许操作在执行时溢出,如果你试图使用一个无法转换为目标的常量表达式在编译时键入 ,你必须告诉编译器你真的知道你在做什么。
例如,在这种情况下,您将丢失信息 - 它将等同于
byte b3 = 0x34;
所以你通常最好只指定一下,为你提供更清晰的代码,不会误导读者。你想要在常量中溢出是相对罕见的 - 大多数时候你应该只指定有效值。
答案 1 :(得分:1)
这不是一个奇怪的行为,byte数据类型的变量的有效范围是0-255
但是当您将HEX 0x1234
值转换为十进制时,您得到{{1 }}。
所以unchecked用于控制溢出检查整数类型的算术运算和转换。
您可以找到4660
实施中经常使用的unchecked
,它执行数值运算来计算最终的哈希码。
总结一下,当整数类型操作的最终结果值无关紧要但可能发生溢出时,应使用GetHashCode()
。
答案 2 :(得分:1)
你不应该用未经检查的方式包围它。未选中允许将危险值类型分配给类型,这可能会导致溢出。
byte b1 = (byte)i;
会在运行时导致溢出或强制转换异常。
byte b2 = (byte)0x1234;
无效,因为您无法在一个字节中存储大于0xFF的值。
byte b3 = unchecked((byte)0x1234);
将把0x34或0x12(取决于CLR实现)放入b3,另一个字节将溢出。
byte b4 = checked((byte)i);
与byte b1 = (byte)i;
相同
byte b5 = (byte)(int)0x1234;
会将0x1234转换为int,然后尝试将其转换为byte。同样,你不能将0x1234转换为一个字节,因为它太大了。