7

为什么在 C# 中示例 A 是有效的、可编译的并且只会包装而示例 B 不会编译?

一种

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;

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

4

3 回答 3

17

您的 B 示例在编译时是常量折叠的,向编译器表明它保证会溢出。

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

例如...

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

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

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

您可以返回编译时溢出检查,因为该值可以完全确定,因此可以进行常量折叠。

于 2010-07-16T16:22:18.570 回答
3

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

你不知道,因为那句话是不正确的。事实上,您知道这是不正确的,因为您提供了一个案例,证明您的陈述是错误的!

我向您推荐 C# 规范的第 7.6.12 节,为了您的方便,我在这里复制了其中的一部分:

对于未被任何已检查或未检查的运算符或语句包围的非常量表达式(在运行时计算的表达式),默认溢出检查上下文是未检查的,除非外部因素(例如编译器切换和执行环境配置)需要检查评估。

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

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

于 2010-07-16T16:43:04.767 回答
1

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

于 2010-07-16T16:23:22.007 回答