代码契约:我们是否必须在委托方法中冗余地指定Contract.Requires(...)语句?

时间:2010-03-29 16:17:50

标签: c# .net .net-4.0 code-contracts

我打算使用新的.NET 4 Code Contracts 功能进行未来的开发。这让我想知道我们是否必须在一系列方法中冗余地指定等效的Contract.Requires(...)语句。

我认为一个代码示例胜过千言万语:

    public bool CrushGodzilla(string weapon, int velocity)
    {
        Contract.Requires(weapon != null);

        // long code

        return false;
    }

    public bool CrushGodzilla(string weapon)
    {
        Contract.Requires(weapon != null);   // specify contract requirement here
                                             // as well???

        return this.CrushGodzilla(weapon, int.MaxValue);
    }

对于运行时检查它并不重要,因为我们最终总是会遇到需求检查,如果失败我们会收到错误。

但是,当我们再次在第二次重载中没有指定合同要求时,这被认为是不好的做法吗?

此外,还有编译时检查的功能,还可能还有代码合同的设计时间检查。在Visual Studio 2010中,它似乎尚不适用于C#,但我认为有一些类似Spec#的语言已经可以使用。当我们编写代码来调用这样的方法时,这些引擎可能会给我们提示,我们的参数当前可以是null

所以我想知道这些引擎是否会一直分析调用堆栈,直到他们找到一个目前不满意的合同方法?

此外,here I learned about the difference between Contract.Requires(...) and Contract.Assume(...)。我想在这个问题的背景下还要考虑差异吗?

2 个答案:

答案 0 :(得分:14)

我认为最佳做法是在每个公共方法上指定所有合同。合同不仅仅是“得到检查的东西” - 它也是有效的文档。如果你调用一个方法但不知道应用了什么合同,那么将合同失败降低是很奇怪的:这会暗示你正在调用的方法中的错误,而不是你的方法。

请注意,如果您在整个项目中使用C#4,则可以考虑使用可选参数和命名参数来避免这么多重载。如果您需要从不支持它们的语言调用代码,那么这没有用。

我强烈怀疑如果你没有在“默认”超载中指定合同,静态检查器( 现在是available for all versions of VS2010)会抱怨合同可能会失败,并且建议添加合同。

答案 1 :(得分:4)

  

此外,还有一个特色   编译时检查,可能   还设计时间检查代码   合同。在Visual Studio 2010中,C#似乎尚不可用......

它可用,但要使用它你必须使用VS2010 终极版本。

警告:这有点推测,但从我用它学到的东西看似是正确的;

您需要手动通过方法传播约束,就像您已经完成的那样。

代码合约可以从方法外部看到的唯一信息就是您所说的。它可以检查 in 方法中的假设和断言,但此分析不会传播。换句话说,CC无法“透视”您的方法,因此它不会自动知道CrushGodzilla(string)需要weapon为非空。

如果使用静态分析,它将在CrushGodzilla(string)中执行检查,并使用有关weapon外部信息意识到CrushGodzilla(string,int)不能为空将建议您添加Requires非null前提条件。 (非传播的事实是,这些知识不会用于分析程序的其余部分。)

我实际上并没有发现静态分析器的任何文件,尽管已经看过了。