我之前在 StackOverflow 上看到了一个帖子,对此进行了一些讨论,但是我再也找不到它了!
我很想知道 System.Diagnostics.Contract 类是否应该在“真实代码”中使用,即生产代码的发布版本?我问这个,因为根据命名空间描述,合同似乎是为了调试或分析目的。
它似乎是一个有用的库,其中功能的前置/后置条件很重要,并且可以避免编写大量 if/then/else 检查的一些工作,所以如果是这种情况,核心库中是否有替代方案?
文档的第 5.1 节(参数验证和合同)详细介绍了您可能考虑使用合同的三种主要使用模式:
因此,至少有一种使用模式,您可以在发布版本中使用合同,至少就官方文档而言。
引用:
在您开始在自己的代码中使用合约之前,您需要做出一些决定,这些决定会影响使用哪些合约形式来进行参数验证以及在哪里使用(参见图 2)。请注意,您可以为您生成的每个托管程序集(每个项目)独立做出这些决定:
合约工具最简单的用法是,如果您决定不需要在发布版本的运行时执行参数验证(用法 1)。在这种情况下,您在开发过程中使用合约工具,而不是在交付的比特上。请记住,您可以将合同参考程序集与您的发布位一起发布,以便客户可以通过调用站点需要检查在其调试版本上对您的参数验证进行运行时检查。
如果您需要在发布版本中验证参数,第二个最简单的方法是在所有版本中打开合同检查(用法 2)。因此,您可以利用这些工具来生成条件的运行时字符串并为您执行合同继承。您可以选择为您的参数验证生成特定的异常,或者使用默认的 ContractException。在发布版本中使用合同工具的风险在于您依赖的工具尚未达到生产质量水平。
最棘手的组合是当您希望在发布版本中验证参数,但您只在调试版本中使用合约工具进行运行时检查,而不是在发布版本中(用法 3)。在这种情况下,您必须按照您已经做的方式继续编写参数验证,即使用 if-then-throw 语句(我们称它们为 legacy-requires)。如果您希望这些是工具可发现的,请在它们之后添加其他合约(例如 Ensures),或者在不存在其他合约的情况下使用 Contract.EndContractBlock()。请注意,由于您没有在发布版本中使用运行时检查工具,因此您不会获得任何合同继承,并且您必须手动重复您对覆盖和接口实现的遗留要求。对于接口和抽象方法,
这也暗示了仅使用框架的其他部分的替代方案是:使用 if-then-throw 的常用方法。