我试图接受Microsoft DevLabs Code Contracts静态分析器并面对我实际上不知道是我还是他们的情况。所以这是代码:
public static int GenerateInBetween(int min, int max)
{
Contract.Requires(min < max);
Contract.Requires((long)(max - min) <= (long)(Int32.MaxValue));
Contract.Ensures(Contract.Result<int>() >= min);
Contract.Ensures(Contract.Result<int>() <= max); // Unpvoven!
long range = max - min;
double basicRandom = new Random().NextDouble();
Contract.Assert(basicRandom >= 0.0);
Contract.Assert(basicRandom <= 1.0); // Unpvoven!
double randomDouble = basicRandom * range;
Contract.Assert(randomDouble >= 0.0);
Contract.Assert(randomDouble <= (double)range); // Unpvoven!
int randomInt32 = (int)randomDouble;
Contract.Assert(randomInt32 >= 0);
Contract.Assert(randomInt32 <= range);
return min + randomInt32;
}
静态分析器坚持认为无法证明评论后的条件和断言。我看不出它何时出错。
编辑即使我通过假设后置条件替换断言仍然未经证实。
答案 0 :(得分:1)
好吧,我认为我最初可以把它分成两部分,但我意识到我的第一个答案实际上并没有回答真正的问题。
以下是您问题的最短版本:
public static void GenerateInBetween(double min, double max)
{
Contract.Requires(min < max);
double range = max - min;
double randomDouble = 1.0 * range;
Contract.Assert(randomDouble <= range);
}
如另一位评论者所提到的,如果您将硬编码1.0更改为值<= 0.5,则它会通过检查。如果是> 0.5然后它失败了。
但是,如果你删除Contract.Requires(min&lt; max)行,那么它总是会失败。
我暂时没有这方面的解释,抱歉。
答案 1 :(得分:0)
我尝试了你的例子并尝试将其归结为最基本的例子。
似乎可能存在一些问题,但我想这里有一个例子可以说明一个主要问题:
public static void TestMethod()
{
double d = MethodReturningDouble();
Contract.Assert(d >= 0.0);
Contract.Assert(d <= 4.0);
}
public static double MethodReturningDouble()
{
// Contract.Ensures(Contract.Result<double>() <= 4.0); // <- without this line the above asserts are unproven
return 3.0;
}
如果没有关于被调用方法的代码协定规范,静态检查器/分析器似乎无法正常工作。 MethodReturningDouble()返回一个常量,静态检查器无法确定断言将始终通过。
总之,对于代码合同规范而言,静态分析器似乎仅,而不是用于一般分析。
可以添加关于您调用的方法的假设(没有定义合同):
例如:
public static void TestMethodUsingRandom()
{
double d = new Random().NextDouble();
Contract.Assume(d <= 1.0);
Contract.Assert(d >= 0.0);
Contract.Assert(d <= 4.0);
}
如果您确定某个特定方法以特定方式运行,那么这是合法的事情。