当您尝试在C#.NET中使用超出其值范围的值声明无符号变量时,它会被标记为编译器错误,但如果您在运行时生成负值并在运行时将其分配给该变量,则值将换行
uint z = -1; // Will not compile
uint a = 5;
uint b = 6;
uint c = a - b; // Will result in uint.MaxValue
有没有一个很好的理由说明为什么无符号变量会在这种情况下换行而不是抛出异常?
感谢。
答案 0 :(得分:26)
在C#中声明未分配的变量未标记错误 - 尝试为变量分配无效值。例如,这是一个在声明后未明确赋值的变量(假设它是本地的):
uint z;
-1不是uint的有效值,不超过0.5,这就是你的例子不能编译的原因。
现在,至于其余部分:整数类型只是溢出 - 就像向int.MaxValue
添加1返回int.MinValue
一样。与程序检查每个溢出操作相比,这是一个显着的性能改进 - 代价是可能没有发现错误。
只有当您处于未经检查的上下文中时才会这样 - 请注意 - 如果您在已检查的上下文中执行任何这些操作,您将获得异常。例如;
class Test
{
static void Main()
{
checked
{
uint a = 5;
uint b = 6;
uint c = a - b;
}
}
}
运行它,你会看到OverflowException
被抛出。如果这是您对整个项目的要求,可以在项目属性中设置它(或使用/checked+
命令行选项编译为csc
。)
编辑:值得注意的是,其他答案表明您可以在检查的上下文中放入少量代码 - 只需c
的声明和分配,甚至只是计算。这一切都很灵活。
答案 1 :(得分:7)
包装是因为默认情况下C#未被选中。如果添加“已选中”块,将检测到溢出:
uint a = 3, b = 4;
checked
{
uint c = a - b; // throws an overflow
}
至于编译器:它只需要有效的数据。
答案 2 :(得分:3)
这只是默认设置 - 您可以更改编译设置以启用运行时arithetic溢出检查。如果你打开它,就会抛出异常,就像你期望的那样。或者,您可以通过将特定操作放入已检查的块中来打开检查。
uint c = checked(a - b);
答案 3 :(得分:0)
可能值得澄清的是,uint
是 unsigned int,而不是未分配的 int。差别很大!
答案 4 :(得分:-1)
始终使用双倍。性能差异微不足道,而且更加灵活和适应性。这种做法可以防止异常并缩短开发时间。肛门的人讨厌它。
答案 5 :(得分:-2)
它包装为负的原因是因为Two's Complement数学用于整数运算。
简短的回答是最重要的位用作符号。零是积极的;一个是消极的。