未经检查的 C# 块中的 System.OverflowException

wil*_*l_w 6 c# unchecked

如果我将 Int32.MinValue 和 -1 传递到Divide()方法中,System.OverflowException尽管块发生在unchecked块中,我还是得到 a 。

    private static int Divide(int n, int d)
    {
        return unchecked (n / d);
    }
Run Code Online (Sandbox Code Playgroud)

这让我感到惊讶 - 除非我错误地阅读了已检查/未检查的文档,否则我希望它只会给我一个溢出的输出(因为 Int32.MinValue / -1 = 2^31 = Int32.MaxValue + 1,我期待溢出到 Int32.MinValue 的值)。相反,它抛出了一个OverflowException.

这是一个显示问题的DotNetFiddle

Joe*_*ell 2

来自关于整数除法的 C# 草案规范

如果左操作数是可表示的最小值intlong值,而右操作数是-1,则会发生溢出。在checked上下文中,这会导致System.ArithmeticException抛出 a (或其子类)。在unchecked上下文中,它是实现定义的,是否System.ArithmeticException抛出 a (或其子类)或是否未报告溢出,结果值是左操作数的值。

我不确定微软在哪里列出了实现定义行为的选择,但显然他们在这里选择了第一个选项。

ECMA-334的附件 B 中列出了此行为以及其他实现定义或未定义的行为。上面的规范草案是最近更新的,但似乎缺少这个附件。

  • 这回答得很清楚了。您的回答让我尝试看看 DotnetFiddle 支持的任何其他编译器中的行为是否发生了变化。它们都产生相同的结果。不过,看到 OverflowException 从受检查的块中弹出有点违反直觉。 (2认同)