checked 和 unchecked 语句(C# 参考)

checkedunchecked 语句指定整型类型算术运算和转换的溢出检查上下文。 默认语句为 unchecked。 当发生整数算术溢出时,溢出检查上下文将定义发生的情况。 在已检查的上下文中,会抛出System.OverflowException;如果在常量表达式中发生溢出,将会导致编译时错误。 在未检查的上下文中,会通过丢弃任何不适合目标类型的高位比特来将操作结果截断。 例如,加法从最大值换行到最小值。 以下示例显示了已检查和未检查上下文中的相同操作:

uint a = uint.MaxValue;

unchecked
{
    Console.WriteLine(a + 3);  // output: 2
}

try
{
    checked
    {
        Console.WriteLine(a + 3);
    }
}
catch (OverflowException e)
{
    Console.WriteLine(e.Message);  // output: Arithmetic operation resulted in an overflow.
}

注意

用户定义的运算符和转换的溢出行为可能与上一段中所述的行为不同。 特别是,用户定义的 checked 运算符可能不会在已检查的上下文中引发异常。

有关详细信息,请参阅算术运算符一文的算术溢出和被零除以及用户定义的 checked 运算符部分。

若要为表达式指定溢出检查上下文,还可以使用 checkedunchecked 运算符,如以下示例所示:

double a = double.MaxValue;

int b = unchecked((int)a);
Console.WriteLine(b);  // output: -2147483648

try
{
    b = checked((int)a);
}
catch (OverflowException e)
{
    Console.WriteLine(e.Message);  // output: Arithmetic operation resulted in an overflow.
}

checkedunchecked 语句和运算符仅影响以文本形式存在于语句块或运算符括号内的操作的溢出检查上下文,如以下示例所示:

int Multiply(int a, int b) => a * b;

int factor = 2;

try
{
    checked
    {
        Console.WriteLine(Multiply(factor, int.MaxValue));  // output: -2
    }
}
catch (OverflowException e)
{
    Console.WriteLine(e.Message);
}

try
{
    checked
    {
        Console.WriteLine(Multiply(factor, factor * int.MaxValue));
    }
}
catch (OverflowException e)
{
    Console.WriteLine(e.Message);  // output: Arithmetic operation resulted in an overflow.
}

在前面的示例中,第一次调用 Multiply 本地函数表明,checked 语句不会影响 Multiply 函数中的溢出检查上下文,因为不会引发任何异常。 在第二次调用 Multiply 函数时,计算函数第二个参数的表达式将在已检查的上下文中计算,并导致异常,因为它以文本形式存在于 checked 语句的块内。

checkedunchecked 的行为取决于类型和操作。 即使对于整数,像 unchecked(x / 0) 这样的操作也总是引发,因为没有合理的行为。 检查类型和操作的行为,以了解checkedunchecked关键字如何影响您的代码。

数值类型和溢出检查上下文

关键字checkedunchecked主要适用于存在合理溢出行为的整型类型。 T.MaxValue + 1 变为 T.MinValue 的回绕行为在 2 的补充引用中是合理的。 表示的值不正确,因为它不适合该类型的存储。 因此,这些比特代表完整结果的低 n 位数。

对于像 decimalfloatdoubleHalf 这样表示更复杂值或补充引用的类型,回绕并不合理。 它不能用于计算更大或更准确的结果,因此 unchecked 没有好处。

floatdoubleHalf具有合理的PositiveInfinityNegativeInfinity饱和值,因此可以在unchecked上下文中检测溢出。 对于 decimal,不存在此类限制,而在 MaxValue 上达到饱和可能导致错误或混淆。 使用 decimal 的操作同时在 checkedunchecked 上下文中引发异常。

受溢出检查上下文影响的操作

溢出检查上下文会影响以下操作:

默认溢出检查上下文

如果未指定溢出检查上下文,CheckForOverflowUnderflow 编译器选项的值将定义非常量表达式的默认上下文。 默认情况下,该选项的值未设置,并且整型算术运算和转换在未检查的上下文中执行。

常量表达式在检查的上下文中默认计算,溢出会导致编译时错误。 可以使用 unchecked 语句或运算符为常数表达式显式指定未检查的上下文。

C# 语言规范

有关更多信息,请参阅 C# 语言规范的以下部分:

另请参阅

  • CheckForOverflowUnderflow 编译器选项