checked 和 unchecked 作用于特定表达式或语句块,控制编译时整数溢出行为:默认 unchecked(静默回绕),需显式 checked 才抛 overflowexception;常量溢出在编译期报错,与运行时 checked 无关;泛型、unsafe 指针运算不受影响;浮点数遵循 ieee 754;不应滥用 unchecked 于业务关键路径,推荐优先使用 math.tryadd 等无异常 api。

checked 和 unchecked 不是用来“开启/关闭全局溢出检查”的开关,而是作用于**特定表达式或语句块**的编译时行为控制。默认情况下,C# 对整数运算使用 unchecked 模式(即溢出不报错、静默回绕),这点和 Java/C++ 都不同——必须显式用 checked 才能抛出 OverflowException。
什么时候必须用 checked?
当你处理用户输入、配置值、序列化数据或任何可能超出目标类型范围的整数计算时,比如解析 JSON 中的大数字、做金额累加、或实现安全的位移逻辑。
- 算术运算(
+、-、*、++、--)和显式转换(如(int)longValue)在checked块中会触发运行时检查 - 注意:常量表达式(如
int.MaxValue + 1)即使不在checked块里,也会在编译时报错——这是编译期检查,和运行时checked无关 - 泛型方法或
unsafe上下文中的指针运算不受checked/unchecked影响
unchecked 的典型使用场景
性能敏感路径、哈希计算、位操作、或明确依赖回绕行为的算法(如 Ring Buffer 索引、CRC 校验)。
- 例如:
unchecked { return (int)(DateTime.UtcNow.Ticks & 0x7FFFFFFF); }—— 利用回绕截断高位,避免分支判断 - 不要在日志、金额、ID 生成等业务关键路径中盲目套
unchecked,容易掩盖逻辑错误 -
unchecked不影响浮点数(float/double)行为,它们遵循 IEEE 754,溢出产生Infinity或NaN
常见错误:把 checked 当成 try/catch 替代品
checked 抛出的是 OverflowException,不是 ArithmeticException;它不能捕获除零、空引用等其他异常,也不能替代输入校验。
- 错误写法:
checked { total += input; }却没处理OverflowException,导致线上崩溃 - 更稳妥的做法是:先用
Math.TryAdd、Math.TryMultiply(.NET 6+)这类无异常 API,或手动比较边界 - 项目级统一策略?可在
.csproj中设<checkforoverflowunderflow>true</checkforoverflowunderflow>,但这会影响所有整数运算,通常不推荐——粒度太粗,易误伤性能
真正难的不是记住语法,而是判断哪一行算术该被保护、哪一行该靠回绕工作。多数人栽在“以为 checked 能兜底一切数值错误”,结果漏掉了隐式转换、移位溢出或浮点精度问题。











