代码合同确保不会证明循环

时间:2011-02-17 23:34:41

标签: c# .net code-contracts

我刚开始玩.Net Code Contracts(在VS2010 Ultimate .Net 4中),试图了解静态检查器能够和不能证明什么。

我正在尝试以下示例: -

public int Mult(int num1, int num2)
    {
        Contract.Requires(num2 >= 0);
        Contract.Ensures(Contract.Result<int>() == (num1 * num2));
        int result = 0;
        for (int i = 0; i < num2; i++)
        {
            result = result + num1;
        }
        return result;
    }

,即通过重复添加来简单实现乘法函数。

静态检查程序无法验证是否满足后置条件: -

CodeContracts: ensures unproven: Contract.Result<int>() == (num1 * num2)

我的功能是否实际上没有正确计算产品..或者还有另一个原因导致静态检查器无法验证需求?循环的存在是否会导致困难?

如果静态检查器很难在循环存在时验证,我可以想象一直有很多警告会很烦人。

我不喜欢选择Assumes告诉它我认为发生了什么,因为通常我的无效假设首先是错误的原因!

因此,当静态检查器无法证明某些东西时,我们该如何去帮助它呢? 例如,我可以将函数重写为递归函数 - 然后检查器是否能够更容易地验证它? (功能编程的拥护者可能会说这应该是首先编写的 - 不改变状态等等!)。还有哪些其他方法可以更改我的代码以使静态检查器更容易?

谢谢!:)

2 个答案:

答案 0 :(得分:1)

静态检查程序永远无法证明这一点,但运行时检查程序将会。

静态检查程序在编译时应用。为了能够证明您的Ensures,它必须能够完全分析您的算法以及您正在做的事情。它不是那么强大。

运行时检查程序当然会在每次函数退出时验证Ensures,并通过适当的单元测试来证明Ensures的有效性。

答案 1 :(得分:0)

一种表达方式是代码契约不是数学家/逻辑学家。

如果代码合同实际上可以推理您的代码,就像您希望“证明”那样

  num1 + num1 + ... + num1     (num2 terms in total)

等于

  num1 * num2

那么你不能只是为它提供任何数学问题,而Code Rects会为你解决它吗?

我不是理论计算机科学专家,我不完全确定以下声明,但我认为这个问题归结为Halting Problem(另请参阅{{3}的底部) })。

因此,我很确定代码契约不可能证明任何任意的数学问题。我不知道Code Contract在推理你的代码方面到底有多远,但我怀疑它不会比检查一些非常基本的,特定的东西更进一步;例如看一下博客文章this blog article by Eric Lippert中的第二个屏幕截图。