问题 在发布版本中使用System.Diagnostics.Contract


我之前在StackOverflow上看过一个关于此问题的讨论,但我无法再找到它!

我有兴趣知道是否应该在'真实代码'中使用System.Diagnostics.Contract类,即生产代码的发布版本?我问这个问题,因为根据命名空间描述,似乎合同旨在调试或分析目的。

它似乎是一个有用的库,其中功能的前/后条件很重要,并且可以避免编写大量if / then / else检查的一些努力,所以如果是这种情况,核心库中是否有替代方案?


6486
2018-01-30 17:58


起源

请不要在标题前加“C#”等。这就是标签的用途。 - John Saunders


答案:


第5.1节(论证验证和合同) 文件 详细介绍了使用合同时可能考虑的三种主要使用模式:

  1. 仅在Debug版本中通过Contracts进行参数验证,而不是在Release版本中。
  2. 在版本构建中也进行验证。
  3. 发布版本中的自定义参数验证,仅在调试版本中的合同。

因此,至少有一种使用模式,您可以在Release版本中使用Contracts,至少在官方文档方面如此。

引用:

在开始在自己的代码中使用契约之前,您需要做出一些决定,这些决策会影响用于参数验证的合同形式以及在何处(参见图2)。请注意,您可以为您生成的每个托管程序集(每个项目)单独做出这些决策:

如果您决定在发布版本中不需要在运行时执行参数验证,则最简单地使用合同工具(用法1)。在这种情况下,您在开发期间使用合同工具,但不在发货位上使用。请记住,您可以将合同引用程序集与发布位一起发送,以便客户端可以通过调用站点需要检查来调试其调试版本上的参数验证。

如果您需要在发布版本中进行参数验证,那么第二种最简单的方法是在所有版本中启用合同检查(用法2)。因此,您可以利用这些工具生成条件的运行时字符串并为您执行合同继承。您可以选择为参数验证生成特定的异常,或者具有默认的ContractException。在发布版本中使用合同工具的风险在于您依赖于尚未达到生产质量级别的工具。

最棘手的组合是在发布版本中需要参数验证时,但是您只在调试版本中使用合同工具进行运行时检查,而不是在发布版本中使用(用法3)。在这种情况下,你必须继续以你已经做的方式编写你的参数验证,即使用if-then-throw语句(我们称之为遗留需求)。如果您希望这些工具可被发现,请在其后添加其他合同(如Ensures),或者如果没有其他合同,则使用Contract.EndContractBlock()。请注意,由于您未在发布版本中使用运行时检查工具,因此您不会获得任何合同继承,并且必须在覆盖和接口实现上手动重复遗留需求。对于接口和抽象方法,如果您编写具有正常需求的合同类并确保表单,您仍然可以获得最大的benet,这样您就可以检查调试版本,它们出现在合同引用程序集中,因此对于依赖项目和静态检查器是可见的。

这也暗示了仅使用框架的其他部分的替代方案:使用if-then-throw的常用方法。


11
2018-01-30 18:57