为什么我应该明确地用“未选中”括起来?
有谁能向我解释这种奇怪的行为吗?
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
注意:这是一个空的控制台应用程序,没有启用算术检查(默认情况下)。 提前谢谢大家。
编辑:我应该足够清楚,但不是所有人。
我确实知道一个字不能容纳一个字节。但是,默认情况下,C# 程序允许某些“危险”操作,主要是出于性能原因。
同样,我可以将两个大整数相加并且根本不会溢出。
我想知道上面的编译时错误:b1 转换/赋值已编译,b2 无法编译。显然没有区别,因为两者都是具有相同值的 Int32。
希望现在已经清楚了。
Is there anyone able to explain me this strange behavior?
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
NOTE: It's an empty Console application, with NO arithmetic checking enabled (as default is).
Thank you everybody in advance.
EDIT: I supposed to be clear enough, but not for all.
I do know that a word can't fit into a byte. But, by default, a C# program allows certain "dangerous" operations, primarily for performance reason.
Similarly, I may sum two large integers together and having no overflow at all.
My wonder was about the compile-time error above: the b1 cast/assignment is compiled, the b2 can't compile. Apparently there's no difference, because both are Int32 having the same value.
Hope it's clear now.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您被 C# 4 规范第 7.19 节的一部分绊倒了:
基本上,要点是,即使您愿意允许操作在执行时溢出,如果您尝试使用无法转换为目标类型的常量表达式 >在编译时,你必须告诉编译器你真的知道你在做什么。
例如,在这种情况下,您将丢失信息 - 这相当于
您通常最好只是指定该信息,以便为您提供更清晰的代码,不会误导读者。您希望在常量中溢出的情况相对较少 - 大多数时候您应该只指定有效值。
You're tripping over a part of section 7.19 of the C# 4 spec:
Basically, the point is that even if you're happy to allow operations to overflow at execution time, if you're trying to use a constant expression which can't be converted to the target type at compile time, you have to tell the compiler that you really know what you're doing.
For example, in this case you're losing information - it'll be equivalent to
so you'd normally be better off just specifying that, to give you clearer code which doesn't mislead the reader. It's relatively rare that you want to overflow in a constant - most of the time you should just specify the valid value instead.
这不是一个奇怪的行为, byte 数据类型是
0-255
但当您将十六进制0x1234
值转换为十进制系统时,您会得到4660
。因此未选中用于控制溢出-检查整型算术运算和转换。
您可以发现
unchecked
经常用于GetHashCode()
实现,该实现执行数字运算来计算最终的哈希码。总而言之,当整数类型运算的最终结果值无关紧要但可能发生溢出时,您应该使用
unchecked
。This is not a strange behaviour, the valid range for a variable of the byte data type is
0-255
but when you convert HEX0x1234
value into decimal system you got4660
.So unchecked used to control the overflow-checking integral-type arithmetic operations and conversions.
You can find that
unchecked
often used inGetHashCode()
implementation which does numeric operations to calculate the final hash code.To summarize you should use
unchecked
when the final result value of integer-type operations is not matter but overflow could happen.你不应该对此不加检查。未选中允许将危险值类型分配给类型,这可能会导致溢出。
byte b1 = (byte)i;
将在运行时导致溢出或转换异常。byte b2 = (byte)0x1234;
无效,因为您无法在字节中存储大于 0xFF 的值。byte b3 = unchecked((byte)0x1234);
将把 0x34 或 0x12(取决于 CLR 实现)放入 b3,另一个字节将溢出。byte b4 = check((byte)i);
与byte b1 = (byte)i;
byte b5 = (byte)(int)0x1234;
会将 0x1234 转换为 int,然后尝试将其转换为 byte。同样,您无法将 0x1234 转换为字节,因为它太大了。You shouldn't surround this with unchecked. Unchecked allows assignment of dangerous value types to a type, which may cause overflows.
byte b1 = (byte)i;
will cause an overflow or cast exception at runtime.byte b2 = (byte)0x1234;
is invalid because you can't store values larger than 0xFF in a byte.byte b3 = unchecked((byte)0x1234);
will place either 0x34 or 0x12 (depending on the CLR implementation) into b3, and the other byte will overflow.byte b4 = checked((byte)i);
is the same asbyte b1 = (byte)i;
byte b5 = (byte)(int)0x1234;
will cast 0x1234 to an int, and then try to cast it to byte. Again, you can't convert 0x1234 to a byte because it's too large.