【问题标题】:Code contracts and overloads代码契约和重载
【发布时间】:2012-07-19 07:58:08
【问题描述】:

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

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 默认值参数)。

如您所见,我也在使用合约来验证输入。

由于逻辑只有第一种方法,那么第二个Contract没有用吗?

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

【问题讨论】:

    标签: c# code-contracts


    【解决方案1】:

    我完全不同意BonyT's answer

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

    你不能把代码契约仅仅看作一个断言工具:控制流运行到另一个重载,它检查参数,所以我不必在这里做。您必须将其视为文档。

    并且在实际层面上:添加代码合同还会将这些合同添加到您生成的 XML 文档中。静态检查器和代码合同编辑器扩展等工具可以向用户显示合同。可以在in this related post by Pascal Cuoqthis post by Jon Skeet 找到其他一些好的论据。

    但是,从运行时的角度来看,它是多余的。至于运行时开销:大多数检查将相对较小,并且没有性能问题。一些检查可能与性能有关(尤其是对集合、数组和枚举的检查),但可以在项目的代码合同属性对话框中单独禁用这些检查(例如,对于发布版本)。一般来说,合同也是如此:您可以将检查降低到您想要的任何级别,以便在非常关键的时候提高性能。如果您构建合同程序集,用户仍将获得静态检查。

    总结一下。指定冗余 Requires 和 Ensures 的缺点:

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

    专业人士:

    • 代码文档
    • 生成的 XML 中的文档
    • 代码用户的静态检查器按预期工作
    • 代码协定编辑器扩展有效
    • ArgumentException 要求发生在被调用的方法中,而不是在远处的某个方法中

    【讨论】:

    • 我完全同意你关于文档方面的看法。但是,它不会引入一些冗余检查吗?在运行时,它不是以 ìf(condition) { if(condition) { }} 结尾吗?
    • 自我记录代码是一个完全有效的目标。在这种情况下,我个人认为没有额外的 Contract.Requires 代码会更清晰。但我接受某些编码标准可能会声明它始终是文档目的所必需的。正如您所指出的,特别是当您打算使用它们生成文档时。
    • 此外,如果您正在运行静态分析器,它会提示您第二种方法应该具有条件,因为您需要通过您的公共方法明确地“渗透”合同要求(通过复制合同或以其他方式检查和处理条件)如果您希望静态分析器运行良好。
    • 我已更正 - 我会删除我的答案,但这似乎不可能,因此将重定向到此答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    相关资源
    最近更新 更多