重构方法参数验证代码到契约-语句反转问题

本文关键字:语句 问题 契约 方法 参数 验证 代码 重构 | 更新日期: 2023-09-27 18:08:11

旧的验证代码通常检查布尔条件,如果为真则抛出异常。

相反,Contract.Requires(...)做相反的事情(为了通过检查,我们需要否定旧的条件)。

我正在重构旧代码,有时会看到一些相当高级的布尔语句,反转它们并不是那么容易,而且只做Contract.Requires(!(*old statements*))看起来很糟糕,非常令人困惑。

如果它有像Contract.RequiresNot()这样的东西,重构在这里会更清晰和直接。

也不能添加静态扩展方法。如果有人遇到这个问题,并找到了一些好的解决方案,我想听听。

重构方法参数验证代码到契约-语句反转问题

您可以尝试保留旧的遗留验证并添加契约。在验证之后立即调用EndContractBlock。从MSDN:

大多数代码以if-then-throw代码的形式包含一些参数验证。在以下情况下,契约工具将这些语句识别为先决条件:

  • 语句出现在方法中任何其他语句之前。
  • 整个语句集后面是一个显式的契约方法调用,例如调用require, ensure, EnsuresOnThrow或EndContractBlock方法。

当if-then-throw语句以这种形式出现时,工具将它们识别为遗留需求语句。如果没有其他契约遵循If -then-throw序列,则以契约结束代码。EndContractBlock方法。

if ( x == null ) throw new ...
Contract.EndContractBlock(); // All previous "if" checks are preconditions

注意,前面测试中的条件是一个否定的前提条件。(实际的前提条件是x != null。)否定的前提条件受到高度限制:它必须按照前面的示例编写;也就是说,它不应该包含else子句,并且then子句的主体必须是单个抛出语句。if测试同时受纯度和可见性规则的约束(参见使用指南),但是throw表达式只受纯度规则的约束。但是,抛出的异常类型必须与发生契约的方法一样可见。

您可以将old statements的结果存储到具有适当名称的布尔变量中。这将摆脱一对令人困惑的括号,也有助于自文档化您的代码=)