代码合同和重载

时间:2012-07-19 07:58:08

标签: c# code-contracts

假设我正在编写一个实用程序库,它定义了一个带有两个重载的方法:

public static class MyClass
{
    public static void DoSomething(string myValue, bool myFlag)
    {
        Contract.Requires<ArgumentNullException>(myValue != null);
        CallExternalMethod(myValue);
        if(myFlag){
            AlsoCallOtherMethod(myValue);
        }        
    }

    public static void DoSomething(string myValue)
    {
        Contract.Requires<ArgumentNullException>(myValue != null);
        DoSomething(myValue, true);
    }
}

作为最佳实践,我只在一个方法中定义逻辑,并使用重载来指定默认参数(.Net 3.5,我不能使用.Net 4默认值参数)。

如您所见,我也是通过使用合同验证输入。

由于逻辑仅在第一种方法中,第二种合同是否无效?

关于运行时检查,我知道它没用,但静态检查器怎么样?理解我的模式是否足够聪明?

1 个答案:

答案 0 :(得分:2)

我完全不同意BonyT's answer

代码合同是文档和方法合同的一部分,就像类型和名称一样。用户/开发人员没有理由认为你只是调用另一个方法重载而没有别的。找出哪种合同适用于某种方法不应该是一种猜谜游戏。如果对参数或返回值有约束,请使用代码约定对其进行记录,即使您在内部 - 隐藏给其他人 - 只需调用另一个方法。

你不能认为Code Contracts只是一个断言工具:控制流运行到另一个重载,它检查参数,所以我不必在这里做。您必须将其视为文档。

在实际层面上:添加代码约定还会将这些合同添加到您生成的XML文档中。静态检查器和Code Contracts Editor Extensions等工具可以向用户显示合同。可以找到其他一些好的参数in this related post by Pascal Cuoqthis post by Jon Skeet

但是,从运行时的角度来看, 是多余的。至于运行时开销:大多数检查都相对较小且没有性能问题。某些检查可能存在性能问题(最明显的是检查集合,数组和枚举),但这些检查可以在项目的“代码约定”属性对话框中单独禁用(例如,对于发布版本)。对于一般合同也是如此:您可以将检查降低到您想要的任何级别,以便在真正关键时提高性能。如果您构建合同程序集,用户仍将进行静态检查。

总结一下。指定冗余需求和确保的内容:

  • 可能会检查两次或更多次相同的情况
  • 由于多重检查(如果您不禁用它)而产生微小的负面性能影响
  • 更多输入(但请参阅these snippets

Pro的:

  • 代码文档
  • 生成的XML中的文档
  • 代码用户的静态检查工具按预期工作
  • 代码合约编辑器扩展程序
  • ArgumentException for Requires发生在被调用的方法中而不是远处的某种方法