Debug.Assert与Code Contract的使用

Car*_*ine 42 c# assert code-contracts

我什么时候应该调试代码合同上的问题,反之亦然?我想检查一个方法的前提条件,我很困惑,选择一个而不是另一个.我有单元测试,我想测试故障情况并期望异常.

在同一方法上使用Debug.Assert和Code契约是一个好习惯.如果是这样,代码的编写顺序是什么?

Debug.Assert(parameter!= null);
Contract.Requires<ArgumentNullException>(parameter != null, "parameter");
Run Code Online (Sandbox Code Playgroud)

要么

Contract.Requires<ArgumentNullException>(parameter != null, "parameter");
Debug.Assert(parameter!= null);
Run Code Online (Sandbox Code Playgroud)

它背后有什么理由吗?

Dwe*_*rly 33

这些是不同的东西.调试断言仅在代码编译为调试时执行,因此仅在调试时检查/断言.我们的想法是将此用于您正在开发的代码的"健全性检查".代码契约可以在调试或发布中使用.他们确保方法的前后条件符合方法的期望(符合合同).还有一个提供类似功能的测试框架,用于检查测试合规性.

如果要确保在开发代码时(以及以后的维护开发中)确保某些事情符合您的预期,请使用Debug.Assert.

如果要确保调试和发布中的条件均为真,请使用代码协定.合同还允许某些形式的静态分析,有助于验证您的程序是"正确的".

在创建单元测试时使用Testing框架断言.

  • 不要忘记:"如果你想在发布版本中做断言,请使用`Trace.Assert`方法." (http://msdn.microsoft.com/en-us/library/tk4kachs(v=vs.110).aspx) (9认同)
  • 没错,但代码合同将检测它调试和发布的问题.如果确保打破代码合约异常,则无需使用Debug.Assert即可获得相同的效果.有人可以说有一个调试.除了代码契约之外,我还提供了一个维护的双重检查(断言是很难忽视的:-)) (3认同)

Stu*_*tLC 26

就个人而言,我不会同时使用Debug.AssertAND代码合同来强制执行新编写的代码中的先决条件 - IMO Code Contracts取代Debug.Assert,因为它们提供了更全面的检查套件,更不用说可以从静态检查中获得的好处执行前的代码获取运行时间.维护两个副本的先决条件检查Debug.Assert,并Contracts会很麻烦.

理由:

  • 您不需要重新编码您可能编码的任何遗留前置条件Debug.Assertthrow代码 - 您可以保留现有的前置条件检查代码并使用Contract.EndContractBlock()
  • 如果在构建合同运行时检查设置为的System.Diagnostics.Debug情况下/d:DEBUG构建,则可以获得相同的未经检查的"释放模式"行为None.文件中的参考6.2.1
  • 合同允许开发人员在代码中更具表现力,因为"为什么"检测到无效状态 - 例如,它是否直接因为带外参数(Contract.Requires).否则Contract.Assert或者Contract.Assume可以检查一般状态,并且可以使用表示离开方法的状态的"保证正确性" Contract.Ensures.并Invariants表示必须始终坚持国家.
  • 最重要的是,静态检查可以在您构建代码时强制执行这些合同 - 这样您就有机会通过设计时间或编译时警告来获取错误,而不必等待运行时间.可以将合同检查添加到持续集成中以查找不合规情况.

需要注意的一点是:如果您要编写故​​意违反合同的单元测试,您可能需要处理ContractException- Jon Skeet 在这里解释得很好.如电线了Contract.ContractFailed处理器在测试设置到调用处理程序SetHandled,然后抛出一个异常公开,你可以赶上并在UT的断言.

  • 很好的解释.现在我懂了.如果一致地使用,它会使开发人员在整个过程中对应用程序状态的假设非常清晰.这只是锦上添花,蛋糕更加细致和完整的异常处理程序,从一开始就很容易放入. (2认同)