9

我打算在未来的开发中使用新的 .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.

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

此外,在这里我了解了Contract.Requires(...)Contract.Assume(...)之间的区别。我想在这个问题的背景下也要考虑这种差异呢?

4

2 回答 2

14

我认为最好在每个公共方法上指定所有合同。合同不仅仅是“检查的内容”——它也是有效的文档。如果您调用一个方法但不知道应用了哪个合同,那么将合同失败降到更低会很奇怪:这表明您正在调用的方法中存在错误,而不是您的方法中的错误。

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

我强烈怀疑,如果您没有在“默认”重载中指定合同,静态检查器(现在可用于所有版本的 VS2010)会抱怨合同可能会失败,并且还会建议添加合同。

于 2010-03-29T16:37:23.180 回答
4

此外,还会有 编译时检查的功能,可能还有代码合约的设计时检查。似乎它在 Visual Studio 2010 中还不能用于 C#...

它是可用的,但要让它工作,你必须使用 VS2010 Ultimate版本。

警告:这有点推测,但从我使用它所学到的知识来看似乎是正确的;

您需要通过您的方法手动传播约束,就像您所做的那样。

Code Contracts 可以从方法外部看到的唯一信息就是你告诉它的信息。它可以检查方法内部的假设和断言,但这种分析不会传播。换句话说,CC 无法“看穿”您的方法,因此它不会自动知道CrushGodzilla(string)需要weapon为非空。

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

尽管已经看过,但我实际上还没有找到任何可以很好地记录该静态分析器的地方。

于 2010-04-13T04:36:48.433 回答