C#中的算术异常

时间:2010-07-16 16:18:43

标签: c# integer-overflow

为什么在C#中示例一个有效的,可编译的并且只是包装而示例B将无法编译?

A

int val = 0;
val = val + Int32.MaxValue +2;

int val = Int32.MaxValue;
val++;

int val = 0;
val = 2147483647 + 1;

int val = 0;
int val = Int32.MaxValue + 1;

默认情况下我知道默认情况下不会检查算术异常,除非您使用配置中的checked方法,块或属性明确地这样做。我的问题更多地与编译器有关,然后是如何发生算术异常。

3 个答案:

答案 0 :(得分:16)

您的B示例在编译时为constant-folded,向编译器指示它确保溢出。

因为您的A示例使用变量,所以表达式不能(完全)常量折叠,因此编译器无法保证这些值会导致溢出。

例如......

int val = 0;
// some other thread changes `val` to -5...
val = val + Int32.MaxValue +2; // no overflow

但是,如果您知道 val不会更改,并将0分配给const int

const int startval = 0;
int val = startval + Int32.MaxValue + 2;

您可以检查编译时溢出检查,因为该值可以完全确定,因此可以不断折叠。

答案 1 :(得分:3)

  

我知道默认情况下不会检查算术异常,除非您使用配置中的checked方法,块或属性明确地这样做

知道,因为该声明不正确。事实上,你知道它是不正确的,因为你提供了一个证明你的陈述是错误的案例!

我推荐你参考C#规范的第7.6.12节,为了方便起见,我在这里重复了一部分:

  

对于未由任何已检查或未检查的运算符或语句包含的非常量表达式(在运行时计算的表达式),除非外部因素(例如编译器开关和执行环境配置),否则将取消选中默认溢出检查上下文)要求进行检查评估。

     

对于常量表达式(可在编译时完全求值的表达式),始终检查默认溢出检查上下文。除非在未经检查的上下文中明确放置常量表达式,否则在表达式的编译时评估期间发生的溢出总是会导致编译时错误。

有关详细信息,请参阅规范。

答案 2 :(得分:1)

它只是与编译时间检查的限制有关。某些事情只能在运行时知道。