我有一个与此类似的结构:
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静态分析器无法应对简单的否定?是否有一些微妙的我遗漏,这意味着它实际上无法推断?
作为奖励问题:分析仪实际上/可以做什么的文档?它有时看起来很有能力,然后就像这个例子那样看起来很简单。在试图证明这些事情时,很高兴知道它的“思维过程”是什么。
答案 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