checked 和 unchecked 语句(C# 参考)
checked
和 unchecked
语句指定整型算术运算和转换的溢出检查上下文,如以下示例所示:
uint a = uint.MaxValue;
unchecked
{
Console.WriteLine(a + 1); // output: 0
}
try
{
checked
{
Console.WriteLine(a + 1);
}
}
catch (OverflowException e)
{
Console.WriteLine(e.Message); // output: Arithmetic operation resulted in an overflow.
}
当发生整数算术溢出时,溢出检查上下文将定义发生的情况,如下所示:
- 在已检查的上下文中,引发 System.OverflowException;如果在常数表达式中发生溢出,则会发生编译时错误。
- 在未检查的上下文中,会通过丢弃任何不适应目标类型的高序位来将操作结果截断。 例如,在加法示例中,它将从最大值包装到最小值,如前面的示例所示。
注意
在相应结果类型的溢出的情况下,用户定义的运算符和转换的行为可能与上一段中所述的行为有所不同。 特别是,用户定义的 checked 运算符可能不会在已检查的上下文中引发异常。
有关详细信息,请参阅算术运算符一文的算术溢出和被零除以及用户定义的 checked 运算符部分。
若要为表达式指定溢出检查上下文,还可以使用 checked
和 unchecked
运算符,如以下示例所示:
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.
}
checked
和 unchecked
语句和运算符仅影响以文本形式存在于语句块或运算符括号内的操作的溢出检查上下文,如以下示例所示:
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
语句的块内。
受溢出检查上下文影响的操作
溢出检查上下文会影响以下操作:
以下内置算术运算符:一元
++
、--
、-
和二元+
、-
、*
和/
运算符,当它们的操作数为整型类型(即整数或字符类型)或枚举类型时。整型类型之间或从
float
或double
到整型类型的显式数字转换。注意
在将
decimal
值转换为整型类型并且结果超出目标类型的范围时,不管溢出检查上下文如何,都始终会引发 OverflowException。从 C# 11 开始,用户定义的 checked 运算符和转换。 有关详细信息,请参阅算术运算符一文的用户定义的 checked 运算符部分。
默认溢出检查上下文
如果未指定溢出检查上下文,则 CheckForOverflowUnderflow 编译器选项的值将定义非常数表达式的默认上下文。 默认情况下,该选项的值未设置,并且整型算术运算和转换在未检查的上下文中执行。
默认情况下,常数表达式在已检查的上下文中计算,如果发生溢出,则会发生编译时错误。 可以使用 unchecked
语句或运算符为常数表达式显式指定未检查的上下文。
C# 语言规范
有关更多信息,请参阅 C# 语言规范的以下部分: