(同样posted on the MSDN forum - 但据我所知,这并没有太大的流量。)
我一直在尝试提供Assert
和Assume
的示例。这是我得到的代码:
public static int RollDice(Random rng)
{
Contract.Ensures(Contract.Result<int>() >= 2 &&
Contract.Result<int>() <= 12);
if (rng == null)
{
rng = new Random();
}
Contract.Assert(rng != null);
int firstRoll = rng.Next(1, 7);
Contract.Assume(firstRoll >= 1 && firstRoll <= 6);
int secondRoll = rng.Next(1, 7);
Contract.Assume(secondRoll >= 1 && secondRoll <= 6);
return firstRoll + secondRoll;
}
(关于能够传入空引用而不是现有Random
引用的业务当然是纯粹的教学法。)
我曾希望如果检查员知道firstRoll
和secondRoll
各自都在[1, 6]
范围内,那么就可以确定总和在[2, 12]
范围内1}}。
这是一个无理的希望吗?我意识到这是一项棘手的事情,确切地说明可能会发生什么......但我希望检查器足够聪明:)
如果现在不支持此功能,那么有没有人知道它是否可能在近期的未来得到支持?
编辑:我现在发现静态检查器中有很复杂的算术选项。使用“高级”文本框,我可以从Visual Studio中试用它们,但据我所知,对它们的作用没有合适的解释。
答案 0 :(得分:14)
我在MSDN论坛上得到了答案。事实证明我几乎就在那里。基本上,如果你拆分“和”合同,静态检查工作会更好。因此,如果我们将代码更改为:
public static int RollDice(Random rng)
{
Contract.Ensures(Contract.Result<int>() >= 2);
Contract.Ensures(Contract.Result<int>() <= 12);
if (rng == null)
{
rng = new Random();
}
Contract.Assert(rng != null);
int firstRoll = rng.Next(1, 7);
Contract.Assume(firstRoll >= 1);
Contract.Assume(firstRoll <= 6);
int secondRoll = rng.Next(1, 7);
Contract.Assume(secondRoll >= 1);
Contract.Assume(secondRoll <= 6);
return firstRoll + secondRoll;
}
没有任何问题。这也意味着该示例更有用,因为它突出了检查器 在分离出的合同中更好地工作的重点。
答案 1 :(得分:1)
我不了解MS Contracts Checker工具,但范围分析是一种标准的静态分析技术;它广泛用于商业静态分析工具,以验证下标表达是合法的。
MS Research在此类静态分析方面有良好的记录,因此我希望将此范围分析作为合同检查器的目标,即使目前尚未检查过。