我为什么要明确地围绕“未选中”?

时间:2011-10-19 14:53:52

标签: c# casting unchecked

有没有人能够解释我这种奇怪的行为?

    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具有相同的值。

希望现在很清楚。

3 个答案:

答案 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转换为一个字节,因为它太大了。