C# 合同的重构方法参数验证代码-语句反转问题

C# 合同的重构方法参数验证代码-语句反转问题,c#,.net,c#-4.0,code-contracts,C#,.net,C# 4.0,Code Contracts,旧的验证代码通常检查布尔条件,如果为真,则抛出异常 相反,Contract.Requires(…)做的恰恰相反(要通过检查,我们需要否定旧条件) 我正在重构旧代码,有时会看到一些相当高级的布尔语句,反转它们并不是那么容易,只需执行Contract.Requires(!(*old statements*)看起来很糟糕,非常混乱 如果它有类似于Contract.RequiresNot()的东西,重构在这里会更加清晰和直接 我们也不能添加静态扩展方法。如果有人遇到了这个问题,并找到了一些好的解决方案,

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

相反,
Contract.Requires(…)
做的恰恰相反(要通过检查,我们需要否定旧条件)

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

如果它有类似于
Contract.RequiresNot()
的东西,重构在这里会更加清晰和直接


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

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

大多数代码都以if-then-throw代码的形式包含一些参数验证。在以下情况下,合同工具将这些声明视为先决条件:

  • 这些语句出现在方法中任何其他语句之前
  • 这类语句的整个集合后面跟着一个显式方法调用,例如对、、或方法的调用
当if-then-throw语句以这种形式出现时,工具会将它们识别为legacy-requires语句。如果没有其他契约遵循If-then-throw序列,则使用该方法结束代码

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


您可以将
旧语句的结果
存储到具有适当名称的布尔变量中。这将消除一对令人困惑的括号,也可以用来自动记录你的代码=)

是的,当我回顾了合同类的可用方法时,我考虑了这一点,我记得它是对遗留问题的建议方法。不过,我可以考虑这种“重构”不完整,单线合同报表看起来更好,如果-扔。它更多的是在旧的解决方案语句之后“无需重构,只需插入EndContractBlock”。同样关于这些限制规则,与合同的方法明确性相比,它们并不是那么自然。。。我会考虑一下,谢谢。如果它们很复杂,你也应该尝试分解它们,至少每次&。好吧,虽然我完全同意你的观点,这会更好,但你必须同意我的观点,分解的显布尔语句也可以被视为错误源。有时也不是那么琐碎。在某些情况下,我宁愿不接触他们,但仍然使用合同。
if ( x == null ) throw new ...
Contract.EndContractBlock(); // All previous "if" checks are preconditions