C# 断言与异常抛出
我已经阅读了大量关于如何以及何时使用断言的文章(以及StackOverflow上发布的一些其他类似问题),我非常理解它们。但是,我仍然不明白是什么样的动机驱使我使用C# 断言与异常抛出,c#,exception,assertions,C#,Exception,Assertions,我已经阅读了大量关于如何以及何时使用断言的文章(以及StackOverflow上发布的一些其他类似问题),我非常理解它们。但是,我仍然不明白是什么样的动机驱使我使用Debug.Assert,而不是抛出一个简单的异常。我的意思是,在.NET中,对失败断言的默认响应是“停止世界”,并向用户显示一个消息框。虽然这种行为可以修改,但我觉得它非常烦人和多余 要做到这一点,我可以抛出一个合适的异常。这样,我就可以在抛出异常之前轻松地将错误写入应用程序的日志,而且,我的应用程序不一定会冻结 那么,为什么我要使
Debug.Assert
,而不是抛出一个简单的异常。我的意思是,在.NET中,对失败断言的默认响应是“停止世界”,并向用户显示一个消息框。虽然这种行为可以修改,但我觉得它非常烦人和多余
要做到这一点,我可以抛出一个合适的异常。这样,我就可以在抛出异常之前轻松地将错误写入应用程序的日志,而且,我的应用程序不一定会冻结
那么,为什么我要使用Debug.Assert
而不是普通的异常呢?将断言放在不应该放的地方可能会导致各种“不想要的行为”,因此在我看来,使用断言而不是抛出异常并不会带来任何好处。你同意我的观点,还是我在这里遗漏了什么
注意:我完全理解“理论上”的区别(调试与发布、使用模式等),但在我看来,我最好抛出异常,而不是执行断言。因为如果在生产版本中发现bug,我仍然希望“断言”失败(毕竟,“开销”小得可笑),所以我最好还是抛出一个异常
编辑:在我看来,如果断言失败,这意味着应用程序进入了某种损坏的、意外的状态。那我为什么要继续执行死刑呢?应用程序是在调试版本还是发布版本上运行并不重要。这两种断言都适用于检查程序员对世界的理解。只有当程序员做了错事时,断言才会失败。例如,永远不要使用断言来检查用户输入 断言测试条件为“不可能发生”。例外情况适用于“不应该发生但确实发生”的情况 断言很有用,因为在构建时(甚至运行时),您可以更改它们的行为。例如,通常在发布版本中,甚至不检查断言,因为它们引入了不必要的开销。这也是值得警惕的:您的测试甚至可能无法执行 如果使用异常而不是断言,则会失去一些价值:
* the condition should never be false if the code is correct,
* the condition is not so trivial so as to obviously be always true, and
* the condition is in some sense internal to a body of software.
断言几乎不应用于检测出现的情况
在软件正常运行期间。
例如,通常断言应该
不用于检查数据库中的错误
用户的输入。然而,这可能会使
使用断言来验证
调用方已检查用户的
输入
基本上,对需要在生产应用程序中捕获/处理的事情使用异常,使用断言执行对开发有用但在生产中关闭的逻辑检查 默认情况下,Debug.Assert将仅在调试版本中工作,因此,如果您想在发布版本中捕获任何类型的不良意外行为,则需要在项目属性中使用异常或启用调试常量(通常认为这不是一个好主意)。另一个要点是: 断言是一个函数或宏 如果是一种假设,它会大声抱怨 不正确。请使用断言来记录 代码中的假设和刷新 出人意料的情况 “在开发过程中,断言不断涌现 提出相互矛盾的假设,, 意外情况、错误值 传递给例程,等等。” 他接着补充了一些关于什么应该和不应该被断言的准则 另一方面,例外情况: “使用异常处理来绘制 注意意外情况。 例外情况应以书面形式处理 一种让他们在比赛中变得明显的方式 开发和可回收时 生产代码正在运行。” 如果你
// 'public facing' method
public int DoSomething(List<string> stuff, object doohickey, int limit) {
// validate user input and report problems externally with exceptions
if(stuff == null) throw new ArgumentNullException("stuff");
if(doohickey == null) throw new ArgumentNullException("doohickey");
if(limit <= 0) throw new ArgumentOutOfRangeException("limit", limit, "Should be > 0");
return DoSomethingImpl(stuff, doohickey, limit);
}
// 'developer only' method
private static int DoSomethingImpl(List<string> stuff, object doohickey, int limit) {
// validate input that should only come from other programming methods
// which we have control over (e.g. we already validated user input in
// the calling method above), so anything using this method shouldn't
// need to report problems externally, and compilation mode can remove
// this "unnecessary" check from production
Debug.Assert(stuff != null);
Debug.Assert(doohickey != null);
Debug.Assert(limit > 0);
/* now do the actual work... */
}