返回码 vs 异常:哪个更好?

Avatar
不若风吹尘
2025-12-28T16:12:50
15
0

好吧,这场辩论每隔几个月就会在开发者 subreddits 和论坛上出现一次

你应该使用返回码还是异常来进行错误处理?

老实说,这里没有百分之百正确的答案!两者都有优缺点,并且根据语言或上下文,其中一种可能比另一种更合理。让我们来看看……


1. 返回码 —— 被称为“老派方式” ——

返回码(例如成功用 0,失败用 -1 等)是最初的方法。你主要在 C 和 C++ 中随处可见它们。 它们非常明确,函数直接返回操作的结果。

➕ 使用返回码的优点

  • 总是知道什么时候出了问题
  • 没有隐藏的控制流——所见即所得
  • 通常速度更快(没有栈展开,没有异常开销)
  • 易于在系统编程、嵌入式开发或性能关键型代码中使用

➖ 使用返回码的缺点

  • 很容易忘记检查返回值(然后,砰,静默失败 😬)
  • 让代码变得冗杂……每个函数调用后面都跟着 if (result != SUCCESS) 很烦人
  • 除非手动构建,否则没有堆栈跟踪或上下文信息

例如:

try
{
 await SendEmailAsync();
}
catch (Exception e)
{
    Log.Exception(e.ToString());
 return -1;
}

看起来不错……直到你在某个地方忘记了其中一个 if 条件。


2. 异常 —— 花哨 & 现代的方式 ——

异常出现得较晚,主要是在 Java、C# 和 Python 这类高级语言中。 其思想是你抛出一个错误,并在其他地方处理它。

➕ 抛出异常的优点

  • 代码更清晰……你可以专注于正常流程,单独处理错误
  • 可以携带详细信息(堆栈跟踪、消息、内部异常……)
  • 更容易处理复杂的错误传播

➖ 抛出异常的缺点

  • 隐藏的控制流——你并不总能看出什么可能会抛出异常
  • 性能损耗(尤其是在紧密循环或低级系统中)
  • 在某些代码库中被过度使用(“所有东西都抛出所有异常”)

例如:

try
{
 await SendEmailAsync();
}
catch (Exception e)
{
 Log.Exception(e.ToString());
    throw e;
}

这种方式更清晰,但如果 SendEmailAsync() 在你的调用栈深处并且失败了,除非你正确记录日志,否则可能很难确切知道哪里出了问题。


那么哪个更好呢? ⚖️

这取决于你在构建什么。

  • 低级系统、驱动程序、实时应用 👉 返回码。 性能和控制更重要。
  • 应用程序级别、业务逻辑或高级 API 👉 异常。 更清晰,也更容易维护。

老实说,有时混合使用两者是有意义的。 例如,你可以在内部使用返回码,在 API 边界处使用异常,以便向用户呈现有意义的错误。


结论

返回码 = 简单、明确,但凌乱。 异常 = 清晰、强大,但可能会咬你一口。 选择适合你的项目和你团队理智水平的方式 😅。

译自:https://abp.io/community/articles/return-code-vs-exceptions-which-one-is-better-1rwcu9yi

Last Modification : 12/29/2025 7:01:01 PM


In This Document