代码合同,如果X&lt; Y和Y = Z + 1为什么X < Z + 1未经证实

时间:2015-11-03 01:33:51

标签: c# code-contracts

我签了一份合同:

for (int i = 0; i < delegateParameterTypes.Length; i++)
{
    Contract.Assert(i < delegateParameterTypes.Length);
    Contract.Assert(delegateParameterTypes.Length == methodParameters.Length + (1));
    // Q.E.D.
    Contract.Assert(i < methodParameters.Length + (1));
}

前两次传球分析很好但是第三次​​说断言是未经证实的,一个接一个?考虑后卫。 这似乎是简单的数学。有什么我想念的吗?

尝试使用字符串数组和本地值似乎工作正常。可能会以某种方式与.Length电话有关吗?我尝试将int交换到UInt16以查看它是否是由于循环中的缓冲区溢出,但那也不是。

1 个答案:

答案 0 :(得分:0)

嗯,我唯一能想到的是静态分析器对这些断言有问题。关注我:

  1. 您致电Contract.Assert(i < delegateParameterTypes.Length);。假设这是真的,我们继续。
  2. 此时,静态分析器不知道即将发生在delegateParameterTypes.Length的呼叫和上面的步骤1之间是否有任何关于Contract.Assert(predicate)的变化。你和我都知道没有发生任何事情,但是分析器没有 - 尽管事实上两行代码是相邻的(谁说没有某些线程在那里触及共享状态?)
  3. 您拨打下一个电话:Contract.Assert(delegateParameterTypes.Length == methodParameters.Length + (1));分析师会对此进行检查,这也没关系。
  4. 此时,分析人员不知道有关delegateParameterTypesmethodParameters - QED的任何内容发生了变化,在下一行中对Contract.Assert(i < methodParameters.Length + (1));进行了未经证实的断言。
  5. 同样,可能存在与这些事物相关联的一些共享全局状态,并且该状态可能在对Contract.Assert的两次调用之间发生了变化。请记住,对于您和我来说,代码看起来是线性和同步的。现实是或可能完全不同,静态分析器不能在连续调用Contract.Assert之间对这些对象的状态做出假设。

    但是可能有用:

    int delegateParameterTypesLength = delegateParameterTypes.Length;
    int methodParametersLength = methodParameters.Length + 1;
    
    for (int i = 0; i < delegateParameterTypesLength; i++)
    {
        Contract.Assert(delegateParameterTypesLength == methodParametersLength);
        // QED
        Contract.Assert(i < methodParametersLength);
    }
    

    通过将长度分配给变量,静态分析器现在可以知道这些值不会在for循环内发生变化,也不会在分配它们的方法外部发生变化。现在,您要将i与已知不会更改的值进行比较。现在,静态分析器可以对这些值的比较做出一些推论,并且应该能够证明这些断言。