我读过很多文章 (和被张贴在计算器上,一对夫妇的其他类似的问题)如何以及何时使用断言,我理解他们。 不过,我仍然不明白什么样的动机应该推动我使用Debug.Assert
而不是抛出一个普通的异常。 我的意思是,在.NET中一个失败的断言默认响应是“阻止世界”,并显示一个消息框,给用户。 虽然这种行为可以被修改,我觉得非常讨厌和冗余要做到这一点,虽然我可以代替,只是抛出一个合适的异常。 这样一来,我可以很容易地编写错误到应用程序的日志就在我抛出异常,而加,我的应用程序时没有必要冻结。
那么,为什么要我,如果有的话,使用Debug.Assert
,而不是一个普通的异常? 配售断言它不应该是可能只是导致各种“不受欢迎的行为”,所以在我的观点,我真的不使用断言,而不是抛出一个异常,是否有所收获。 你是否同意我的观点,还是我失去了一些东西?
注:我完全理解上的差异是什么“理论”(调试VS版本,使用模式等),但我看到它,我会过得更好抛出一个异常,而不是执行断言。 因为如果一个bug在生产发行后发现,我还是想在“断言”失败(毕竟“开销”是小得可笑),所以我会更好抛出异常来代替。
编辑:我看到它的方式,如果断言失败,这意味着该应用程序进入某种损坏,意外状态。 所以,我为什么要继续执行? 如果应用程序在调试或发行版本的运行没关系。 这同样适用于这两种
Answer 1:
虽然我同意你的推理是合理的 -也就是说,如果断言被意外破坏,这是有道理的抛出暂停执行-我个人不会在声明的地方使用异常。 这是因为:
正如其他人所说,断言应当记录是不可能的 ,以这样的方式,如果涉嫌不可能的情况来传递,开发商被告知的情况。 例外,相比之下,对于特殊的,不太可能的,或错误的情况下提供一个控制流机构,但并非不可能的情况。 对我来说,最关键的区别是这样的:
这就是为什么我不会例外替换断言。 如果断言实际上不能开火,然后用一个异常替换它意味着你必须在你的程序中无法验证的代码路径 。 我不喜欢不可测的代码路径。
Answer 2:
断言是用于检查世界的程序员的理解。 如果程序员做了错事的断言失败了而已。 例如,切勿使用断言来检查用户输入。
断言测试条件“不可能发生”。 例外情况是条件“不应该发生,但这样做”。
断言是有用的,因为在制作的时候(甚至是运行时间),你可以改变自己的行为。 例如,经常在发布版本中,断言甚至没有检查,因为他们不需要介绍的开销。 这也是一件值得警惕的:你的测试甚至可能不会被执行。
如果你使用异常,而不是断言,你失去了一些值:
该代码是更详细的,因为测试和抛出异常是至少两行,而断言是唯一的一个。
你的测试扔代码将始终运行,而资产可以编译了。
你失去了与其他开发商一些沟通,因为声称具有比检查并引发产品代码不同的含义。 如果你真的测试程序的断言,使用断言。
这里更多: http://nedbatchelder.com/text/assert.html
Answer 3:
编辑: 在回答到编辑/注意,您在您的文章提出:这听起来像使用的例外是使用超过使用断言的事情,你所要完成的类型正确的事情。 我想你打的心理障碍是,你正在考虑的例外和断言实现同样的目的,所以你正在试图找出哪一个会是“正确”的使用。 虽然可能会有怎样的断言和异常可以用一定的重叠,不要混淆,对他们是不同的解决方案,以同一problem-他们不是。 断言和例外每个人都有自己的目的,优点和缺点。
我要键入在我自己的话回答,但这样做的更好的概念比正义我会:
C#站:断言
使用断言语句都可以赶上在运行时程序中的逻辑错误的有效途径,但他们很容易被过滤掉的生产代码。 一旦开发完成后,对编码错误这些冗余测试的运行时成本可以简单地通过定义预处理符号NDEBUG编译期间[即禁用所有断言]消除。 可以肯定,但是,要记住,代码放置在断言自己会在量产版被省略。
断言最适合用来测试一个条件,只有当所有下列条件成立:
* 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.
断言应该几乎从来没有被用来检测的软件的正常运行过程中出现的情况。 例如,通常断言不应该用于检查在用户的输入错误。 它可能,但是,是有意义的使用断言来验证主叫方已经查了用户的输入。
基本上,使用的是需要捕获/在生产应用程序处理的事例外,使用断言进行逻辑检查,这将是对发展有用的,但在生产关闭。
Answer 4:
我认为(人为)实际的例子可能有助于阐明的区别:
(改编自MoreLinq的批次扩展 )
// '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... */
}
因此,作为埃里克利珀等人说,你只断言,你希望是正确的东西,以防万一你 (开发商)不小心用错了别的地方,这样你就可以修复你的代码。 你基本上抛出异常时,你有没有控制权或无法预料会发生什么进来, 如用户输入 ,所以,无论把它坏的数据可以适当地(例如,用户)响应。
Answer 5:
从另一个块代码完成 :
“一个说法是,抱怨一声,如果假设是不正确的函数或宏。使用断言文档中的代码所做的假设,并冲出意外情况。...
“在开发过程中,断言冲洗矛盾的假设,意外情况,传递给程序错误值,等等。”
他接着补充什么应该和不应该被认定的一些准则。
在另一方面,异常:
“使用异常处理提请注意意外情况。特殊情况下应在的方式,使开发过程中他们明显和可恢复生产代码运行时进行处理。”
如果你没有这本书,你应该买它。
Answer 6:
默认情况下,Debug.Assert的仅在调试版本中工作,所以如果你想赶上任何形式的在您的版本不好的意外行为建立你需要使用异常或在您的项目属性开启调试不变(这是在考虑一般不是一个好主意)。
Answer 7:
使用的东西是可能的,但不应该发生的断言(如果它是不可能的,为什么你会放一个说法对吗?)。
那岂不是很喜欢的情况下,使用一个Exception
? 为什么要使用一个断言,而不是一个的Exception
?
因为应该有代码,得到您的说法之前调用,将停止断言的参数是假的。
通常有你之前没有代码Exception
,保证它不会被抛出。
为什么好事Debug.Assert()
正式版编译了吗? 如果你想知道关于它的调试,难道你想知道关于它的刺?
你只在开发过程中需要它,因为一旦你找到Debug.Assert(false)
的情况下,你再编写代码,以保证Debug.Assert(false)
不会再发生。 一旦开发完成后,假设你已经找到了Debug.Assert(false)
的情况和固定。其中, Debug.Assert()
可以安全地编译后,因为他们现在是多余的。
Answer 8:
假设你是一个相当大的团队的一员,有几个人在同一通用代码库所有的工作,包括班重叠。 您可以创建一个由其它几种方法调用的方法,避免锁争你没有一个单独的锁添加到它,而是“假设”它以前通过与特定的锁调用的方法锁定。 如,Debug.Assert的(RepositoryLock.IsReadLockHeld || RepositoryLock.IsWriteLockHeld); 其他开发者可能会忽略的评价是说调用的方法必须使用锁,但也不能忽略这一点。
文章来源: Debug.Assert vs Exception Throwing