使用断言还是引发异常?


38

通常,当我编写一个函数时,我想确保其输入有效,以便尽早检测到此类错误(我相信这些被称为前提条件)。当前提条件失败时,我总是抛出异常。但是我开始怀疑这是否是最佳做法,如果不是,则断言是否更合适。

所以我应该什么时候做:什么时候使用断言,什么时候抛出异常?


3
我认为应该在stackoverflow上问这个问题,尽管在那里可能被问过十几遍了,所以您可能已经在这里找到了很多答案。
user281377 2010年

Answers:


50

断言仅应用于验证逻辑上不可能为假的条件(请参阅:健全性检查)。这些条件应仅基于您自己的代码生成的输入。基于外部输入的任何检查都应使用异常。

我倾向于遵循的一个简单规则是使用断言来验证私有函数的参数,并对公共/受保护函数的参数使用异常。


关于将异常用于外部输入的好地方。试图创建时的写入问题/到文件/数据库等-我还输出添加到太
ChrisF

13
不可避免地,您会发现这些断言在生产中被触发。+1用于使用assert 验证私有内容!也许您可以说“在完全控制输入时使用断言”?
Frank Shearar

1
至少在Java中,通常必须使用-ea命令行参数启用断言检查。这意味着断言实际上是无操作的,除非您明确将它们打开。
Bill Michell 2012年

29

断言用于查找编程错误。删除所有断言后,您的程序也必须运行良好。

另一方面,异常是针对即使程序完美的情况也可能发生的情况。它们是由硬件,网络,用户等外部因素引起的。


这是一个很好的表达方式。如果用户输入了不正确的内容,则引发异常。如果输入正确但仍然存在问题,则抛出一个断言。
Mateen Ulhaq '18 -10-22

3

典型的编程实践是从生产/发布版本中编译出断言。断言仅在内部测试期间有助于发现假设失败。您不应该承担外部机构的行为,因此您不应该对来自网络或用户的事件进行断言。在断言失败的情况下,为生产构建编写处理代码也是一个好习惯。

例如在C中

int printf(const char *fmt, ...)
{
  assert(fmt);  // may fail in debug build but not in production build
  if (!fmt) return -1; // handle gracefully in production build
  ...
}

异常应该内置到生产版本中。异常的替代方法是返回错误而不是断言。


2
我认为在相同条件下将优美的行为置于断言之后不是一个好主意。不可避免地,由于优美行为仅存在于生产版本中,因此原本应该用来处理优美行为的代码将受到不良测试,并且崩溃的程度将与没有受到保护的代码一样糟糕,甚至更糟。
塞巴斯蒂安·雷德尔

0

对于我而言,断言的一个问题是它们在Java中默认为禁用。

我们使用故障优先策略,其中该程序(可能已经无人值守运行了多年)需要尽早崩溃,以避免由于数据损坏(以意外形式)而导致数据损坏。这就是我们用来检查的内容,通过使用断言,我们基本上会冒风险使其不活动。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.