我应该何时在代码合同上调试。或者反之亦然?我想检查一个方法的前提条件,我很困惑,选择一个而不是另一个。我有单元测试,我想测试故障情况并期望例外。
在同一方法上使用Debug.Assert和Code契约是一个好习惯。如果是这样,代码的编写顺序是什么?
Debug.Assert(parameter!= null);
Contract.Requires<ArgumentNullException>(parameter != null, "parameter");
或
Contract.Requires<ArgumentNullException>(parameter != null, "parameter");
Debug.Assert(parameter!= null);
背后有什么理由吗?
答案 0 :(得分:30)
这些是不同的东西。调试断言仅在代码编译为调试时执行,因此仅在调试时检查/断言。我们的想法是将此用于您正在开发的代码的“健全性检查”。代码契约可以在调试或发布中使用。他们确保方法的前后条件符合方法的期望(符合合同)。还有一个提供类似功能的测试框架,用于检查测试合规性。
当您需要确保在开发代码时(以及在以后的维护开发中)确保某些内容符合您的预期时,请使用Debug.Assert。
如果要确保调试和发布中的条件均为真,请使用代码协定。合同还允许某些形式的静态分析,这有助于验证您的程序是否“正确”。
在创建单元测试时使用Testing框架断言。
答案 1 :(得分:24)
就我个人而言,我不会同时使用Debug.Assert
和代码合同来强制执行新编写的代码中的先决条件 - IMO代码合同取代Debug.Assert
,因为它们提供了更全面的检查套件,更不用说了可以从静态检查中获得的好处,可以在代码运行时之前执行。在Debug.Assert
和Contracts
中维护重复的前置条件检查将非常麻烦。
理由:
Debug.Assert
或throw
代码中编码的任何旧前提条件 - 您可以保留现有的前提条件检查代码和terminate it with Contract.EndContractBlock()
System.Diagnostics.Debug
的情况下构建,则/d:DEBUG
在没有None
的情况下构建时,您可以获得相同的未经检查的“发布模式”行为。 Ref 6.2.1 in the Docs Contract.Requires
)。否则Contract.Assert
或Contract.Assume
可以检查一般状态,并且可以使用Contract.Ensures
表示离开方法时状态的“保证正确性”。 Invariants
表示必须始终保持国家。有一点需要注意:如果您要编写故意违反合同的单元测试,您可能需要处理ContractException
- Jon Skeet很好地解释了这一点here。例如将测试设置中的Contract.ContractFailed
handler连接到调用SetHandled
的处理程序,然后抛出一个公共异常,您可以在UT中捕获并断言。