已选中和未选中的语句(C# 参考)
checked
和 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 运算符部分。
若要为表达式指定溢出检查上下文,还可以使用 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
语句的块内。
其行为 checked
取决于 unchecked
类型和操作。 即使对于整数,操作也总是 unchecked(x / 0)
会引发,因为没有合理的行为。 检查类型和操作的行为,以了解代码和unchecked
关键字如何影响checked
代码。
数值类型和溢出检查上下文
关键字checked
unchecked
主要适用于存在合理溢出行为的整型类型。 换行行为,即 T.MaxValue + 1
在两者补充值中变得 T.MinValue
合理。 表示的值不正确,因为它不适合该类型的存储。 因此,位代表完整结果的下 n 位。
对于类型(例如decimal
,float
和double
Half
表示更复杂的值或补充值)而言,换行并不合理。 它不能用于计算更大或更准确的结果,因此 unchecked
没有好处。
float
, double
并且 Half
具有合理的饱和值 PositiveInfinity
, NegativeInfinity
因此可以在上下文中 unchecked
检测溢出。 因此 decimal
,不存在此类限制,饱和 MaxValue
可能导致错误或混淆。 在上下文checked
unchecked
中使用decimal
引发的操作。
受溢出检查上下文影响的操作
溢出检查上下文会影响以下操作:
以下内置算术运算符:一元
++
、--
、-
和二元+
、-
、*
和/
运算符,当它们的操作数为整型类型(即整数或字符类型)或枚举类型时。整型类型之间或从
float
或double
到整型类型的显式数字转换。注意
在将
decimal
值转换为整型类型并且结果超出目标类型的范围时,不管溢出检查上下文如何,都始终会引发 OverflowException。从 C# 11 开始,用户定义的 checked 运算符和转换。 有关详细信息,请参阅算术运算符一文的用户定义的 checked 运算符部分。
默认溢出检查上下文
如果未指定溢出检查上下文,CheckForOverflowUnderflow 编译器选项的值将定义非常量表达式的默认上下文。 默认情况下,该选项的值未设置,并且整型算术运算和转换在未检查的上下文中执行。
常量表达式在检查的上下文中默认计算,溢出会导致编译时错误。 可以使用 unchecked
语句或运算符为常数表达式显式指定未检查的上下文。
C# 语言规范
有关更多信息,请参阅 C# 语言规范的以下部分: