检查未经检查
checked
和 unchecked
关键字定义了操作如何处理数学溢出。checked
和 unchecked
关键字上下文中的溢出是指整数算术运算产生的值大于目标数据类型可以表示的值。
当 checked
块中发生溢出时(或者当编译器设置为全局使用检查算术时),将抛出异常以警告不期望的行为。同时,在 unchecked
块中,溢出是静默的:没有抛出异常,并且值将简单地环绕到相反的边界。这可能导致细微,难以发现的错误。
由于大多数算术运算是在不大或不足以溢出的值上完成的,因此大多数情况下,不需要将块明确定义为 checked
。在对可能导致溢出的无界输入进行算术运算时需要小心,例如在递归函数中进行算术运算或在进行用户输入时。
checked
和 unchecked
都不会影响浮点算术运算。
当块或表达式声明为 unchecked
时,允许其中的任何算术运算溢出而不会导致错误。需要此行为的示例是计算校验和,其中允许值在计算期间环绕:
byte Checksum(byte[] data) {
byte result = 0;
for (int i = 0; i < data.Length; i++) {
result = unchecked(result + data[i]); // unchecked expression
}
return result;
}
unchecked
最常见的用途之一是为 object.GetHashCode()
(一种校验和)实现自定义覆盖。你可以在此问题的答案中看到关键字的用法: 重写的 System.Object.GetHashCode 的最佳算法是什么? 。
当块或表达式声明为 checked
时,任何导致溢出的算术运算都会导致 OverflowException
被抛出。
int SafeSum(int x, int y) {
checked { // checked block
return x + y;
}
}
已检查和未检查可以是块和表达形式。
已检查和未检查的块不会影响被调用的方法,只会在当前方法中直接调用操作符。例如,Enum.ToObject()
,Convert.ToInt32()
和用户定义的运算符不受自定义检查/未检查上下文的影响。
注意 :可以在项目属性中或通过 / checked [+ | - ] 命令行开关更改默认溢出默认行为(已检查与未检查)。默认情况下,检查调试版本的操作是常见的,而对于版本版本则是未选中的操作。然后,只有在默认*方法不适用且需要明确行为以确保正确性的*情况下,才会使用 checked
和 unchecked
关键字。