应明确需要检测并中断非法整数运算时才用checked;默认unchecked更高效,常见于用户输入金额累加、数组长度计算等场景。

什么时候该用 checked 而不是依赖默认行为
默认情况下,C# 对整数算术溢出是「静默忽略」的——比如 int.MaxValue + 1 会绕回 int.MinValue,不报错也不警告。这在金融、计费、索引计算等场景极危险。只有当你明确需要检测并中断非法运算时,才启用 checked;否则保持默认(即 unchecked 上下文)更高效。
常见触发点包括:用户输入参与的金额累加、数组长度动态计算、循环步长叠加、ID 生成器递增。
checked 块和 checked 表达式的区别与选择
checked 可以修饰语句块或单个表达式,二者语义一致,但作用域不同:
-
checked { int x = int.MaxValue + 1; }—— 整个块内所有整数运算都受检 -
int x = checked(int.MaxValue + 1);—— 仅括号内表达式受检,不影响前后代码 - 若写成
int x = checked(int.MaxValue) + 1;,则checked只包住int.MaxValue(无意义),加法仍不受检——这是典型误用
编译器选项 /checked+ 的实际影响
项目属性中勾选「检查算术溢出/下溢」,等价于整个编译单元默认进入 checked 上下文。但注意:
- 它只影响
int、short、long、byte等整型,对float、double、decimal无效(decimal本身就会溢出抛异常) - 它不能覆盖显式写的
unchecked块——后者优先级更高 - 开启后可能暴露隐藏 bug,比如旧代码里依赖绕回逻辑做哈希或位掩码,此时会直接崩掉
捕获 OverflowException 的正确姿势
checked 触发的是 OverflowException,不是 ArithmeticException 或 ArgumentException,别抓错类型:
try
{
int result = checked(1000000 * 1000000);
}
catch (OverflowException)
{
// 正确:专门处理溢出
}
catch (Exception ex) when (ex is not OverflowException)
{
// 不建议:泛捕获掩盖问题
}注意:.NET 5+ 中 OverflowException 是非致命异常,可安全捕获;但在性能敏感路径(如 inner loop)中频繁抛异常代价高,应优先用预检查(如比较操作数与 int.MaxValue - operand)替代 checked + 异常。
最易被忽略的一点:checked 对引用类型、浮点数、decimal 加减乘除完全无作用——它只约束有符号/无符号整型的四则与一元运算。










