在数字领地里,性能讨论最怕“直觉先行、测量滞后”。
try-catch 正是一个高频误解点:很多人担心它“天然慢”,于是过度回避;也有人把异常当分支逻辑使用,导致吞吐量坍缩。
这篇文章只讲底层逻辑,不讲玄学结论。

✦ 核心结论 (Core Conclusion)

结论可以压缩成两句:

  1. 无异常抛出时try-catch 的额外开销通常极低,在多数业务场景可忽略。
  2. 发生异常并被捕获时,成本非常高,远高于普通条件判断与分支执行。

换句话说:贵的是“抛出异常”这件事,不是“写了 try 块”这件事。

✦ 为什么正常路径几乎不慢 (Why Happy Path Is Cheap)

在现代 CLR + JIT 体系中,try 区域对应的异常处理元数据主要体现为异常处理表(EH Table),用于在故障发生时定位处理器。

✦ 运行时行为 (Runtime Behavior)

  • 正常执行时,CPU沿指令星轨顺序推进;
  • 不发生异常时,不会进入异常分派流程;
  • 因此,try 的存在本身通常不会造成显著热点损耗。

这也是为什么你在微基准中常看到:
“纯计算循环 + try” 与 “纯计算循环不加 try” 时间接近,差异常落在抖动区间。

✦ 为什么异常路径非常昂贵 (Why Throw Is Expensive)

当异常真正发生,运行时会切换到完全不同的处理轨道:

✦ 调用栈展开与匹配 (Stack Unwinding)

CLR 需要沿调用栈逐层查找可匹配的 catch
调用链越深、栈越复杂,代价越高。

✦ 异常对象与堆栈信息 (Exception Object & Stack Trace)

异常创建和堆栈采集需要额外分配与元信息处理。
这部分会直接放大 CPU 与内存压力。

✦ 流程中断效应 (Control-Flow Disruption)

异常会打断 CPU 对“常规路径”的优化预期。
在高频路径中反复触发异常,吞吐会出现断崖式下降。

✦ 典型误用:用异常做控制流 (Anti-Pattern: Exceptions as Flow Control)

下面是常见反模式:

1
2
3
4
5
6
7
8
9
10
11
for (int i = 0; i < 10000; i++)
{
try
{
int value = int.Parse(userInput);
}
catch (FormatException)
{
// 忽略
}
}

如果 userInput 频繁非法,这段代码会持续走“昂贵路径”。

✦ 推荐模式:TryParse 系列 (Preferred Try-Pattern)

1
2
3
4
5
6
7
8
9
10
11
for (int i = 0; i < 10000; i++)
{
if (int.TryParse(userInput, out var value))
{
// 成功逻辑
}
else
{
// 失败逻辑
}
}

这才是高频输入校验的正确底层逻辑:
把可预期失败留在普通分支,不要升级为异常机制。

✦ async/await 场景的边界 (Async/Await Considerations)

异步方法中的异常会被封装进 Task,在 await 时再重新抛出。
这不改变本质规律:异常路径仍旧昂贵

在异步循环、批处理、消息消费等吞吐敏感路径中,应避免“预期失败 = 抛异常”的设计。

✦ 工程实践建议 (Engineering Practices)

✦ 在边界层使用 try-catch (Use at Boundaries)

适合放在这些位置:

  • I/O 边界(文件、网络、数据库)
  • 第三方库调用边界
  • 服务入口与任务调度入口

目标是:隔离故障、记录上下文、维持系统稳定。

✦ 捕获后快速收敛 (Fail Fast in Catch)

catch 中优先做:

  1. 记录关键日志(上下文、参数、异常类型)
  2. 清理必要资源
  3. 快速返回/终止当前流程

避免在 catch 内继续堆叠重计算。

✦ 重抛请使用 throw; (Rethrow Correctly)

1
2
3
4
5
6
7
8
9
try
{
DoWork();
}
catch (Exception)
{
// 记录后保留原始调用栈
throw;
}

不要使用 throw ex;,它会破坏原始堆栈可追溯性,不利于定位故障星轨。

✦ 最终归档 (Final Takeaway)

在 C# 中,try-catch 不是性能敌人;
频繁抛异常才是。

如果你的路径是“常规业务 + 可预期失败”,优先选择 if / TryXxx
如果你的路径是“不可预期故障 + 边界防护”,就应当坚定使用异常机制。

在数字领地,性能优化从来不是“禁用工具”,而是“把工具放在正确轨道上”。