CodeContracts不能证明是一个简单的保证

时间:2013-11-19 10:58:07

标签: c# code-contracts

我有一个与此类似的结构:

public struct Test
{
  public int x;
  public int y;

  public static bool AreEqual(Test lhs, Test rhs)
  {
    Contract.Ensures(Contract.Result<bool>() == ((lhs.x == rhs.x) && (lhs.y == rhs.y)));
    return (lhs.x == rhs.x) && (lhs.y == rhs.y);
  }

  public static bool AreNotEqual(Test lhs, Test rhs)
  {
    Contract.Ensures(Contract.Result<bool>() == !((lhs.x == rhs.x) && (lhs.y == rhs.y)));
    return !AreEqual(lhs, rhs);
  }
}

Ensures证明AreEqual没有问题,但它无法证明AreNotEqual的{​​{1}}。

如果Ensures条件从A == B更改为!A || B!B || A,这在逻辑上是等效的,那么它没有任何问题,但是更加详细不太可读。

同样,如果我只是将等式逻辑放在!AreEqual(lhs, rhs)而不是{{1}},那就没问题了,但是再次,这是重复,我宁愿不必投入。

我的问题是:为什么CodeContracts静态分析器无法应对简单的否定?是否有一些微妙的我遗漏,这意味着它实际上无法推断?

作为奖励问题:分析仪实际上/可以做什么的文档?它有时看起来很有能力,然后就像这个例子那样看起来很简单。在试图证明这些事情时,很高兴知道它的“思维过程”是什么。

1 个答案:

答案 0 :(得分:0)

我不知道会回答奖金问题的文件。我也无法具体回答为什么它不能证明后置条件是书面的,但如果你的最终目标只是减少相等逻辑的重复,这可能会有所帮助。

这些方法不会导致可见的状态更改,因此可以使用[Pure]属性进行标记。此时,.Ensures中的AreNotEqual可以直接引用AreEqual。然后静态分析器有足够的信息,你只有在AreEqual中表示的相等逻辑。

public struct Test
{
    public int x;
    public int y;

    [Pure]
    public static bool AreEqual(Test lhs, Test rhs)
    {
        Contract.Ensures(Contract.Result<bool>() == ((lhs.x == rhs.x) && (lhs.y == rhs.y)));
        return (lhs.x == rhs.x) && (lhs.y == rhs.y);
    }

    [Pure]
    public static bool AreNotEqual(Test lhs, Test rhs)
    {
        Contract.Ensures(Contract.Result<bool>() == !AreEqual(lhs, rhs));
        return !AreEqual(lhs, rhs);
    }
}

// CodeContracts: Checked 4 assertions: 4 correct