问题描述
如果我将 Int32.MinValue 和 -1 传递给 Divide()
方法,尽管该块发生在 System.OverflowException
块中,但我仍会得到一个 unchecked
。
private static int Divide(int n,int d)
{
return unchecked (n / d);
}
这让我感到惊讶 - 除非我错误地阅读了 documentation 的检查/未检查,否则我希望它只会给我一个溢出的输出(因为 Int32.MinValue / -1 = 2^31 = Int32.MaxValue + 1,我期望溢出到 Int32.MinValue 的值)。相反,它抛出了一个 OverflowException
。
这是显示问题的 DotNetFiddle。
解决方法
From the C# draft specification on integer division:
如果左操作数是最小可表示的 int
或 long
值,而右操作数是 -1
,则发生溢出。在 checked
上下文中,这会导致抛出 System.ArithmeticException
(或其子类)。在 unchecked
上下文中,它是实现定义的,即是抛出 System.ArithmeticException
(或其子类)还是未报告溢出,结果值是左操作数的值。
我不确定 Microsoft 在哪里列出了实现定义行为的选择,但显然他们在这里选择了第一个选项。
ECMA-334 的附录 B 中列出了这种和其他实现定义或未定义的行为。 上面的规范草案是最近更新的,但似乎缺少这个附件。