这两种说法有什么区别?
Contract.Requires(string.IsNullOrWhiteSpace(userName));
Contract.Assume(string.IsNullOrWhiteSpace(userName));
最佳答案
想象一下,你有一个这样的方法:
bool ContainsAnX(string s)
{
return s.Contains("X");
}
现在,如果您通过
null
,此方法将始终失败到它,所以你要确保这永远不会发生。这就是 Contract.Requires
是为了。它设置了 前置条件对于方法,必须为真才能使方法正确运行。在这种情况下,我们将有:bool ContainsAnX(string s)
{
Contract.Requires(s != null);
return s.Contains("X");
}
( 注意 :
Requires
和 Ensures
必须始终位于方法的开头,因为它们是有关整个方法的信息。Assume
用于代码本身,因为它是有关代码中该点的信息。)现在,在调用“ContainsAnX”方法的代码中,您必须确保字符串不为空。您的方法可能如下所示:
void DoSomething()
{
var example = "hello world";
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
这样可以正常工作,静态检查器可以证明
example
不为空。但是,您可能正在调用外部库,这些库没有关于它们返回的值的任何信息(即它们不使用代码协定)。让我们更改示例:
void DoSomething()
{
var example = OtherLibrary.FetchString();
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
如果
OtherLibrary
不使用代码契约,静态检查器会提示 example
可能为空。也许他们的库文档说该方法永远不会返回 null (或者永远不应该!)。在这种情况下,我们比静态检查器知道的更多,所以我们可以告诉它
Assume
变量永远不会为空:void DoSomething()
{
var example = OtherLibrary.FetchString();
Contract.Assume(example != null);
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
现在,静态检查器就可以了。如果你启用了运行时契约,Assume 也会在运行时被检查。
您可能需要 Assume 的另一种情况是,当您的先决条件非常复杂并且静态检查器很难证明它们时。在这种情况下,您可以稍微插入一下以帮助它:)
在运行时行为方面,使用 Assume 和 Requires 之间不会有太大区别。但是,静态检查器的结果会有很大的不同。每个人的含义也不同,在失败的情况下谁对错误负责:
关于.net-4.0 - 代码契约(Contract) - 假设与要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4758460/