.net 4.0 代码契约-假设vs要求
这两种说法有什么不同.net 4.0 代码契约-假设vs要求,.net-4.0,code-contracts,.net 4.0,Code Contracts,这两种说法有什么不同 Contract.Requires(string.IsNullOrWhiteSpace(userName)); Contract.Assume(string.IsNullOrWhiteSpace(userName)); 它只不同于设计时间/静态分析时间 合同。假设: 指示代码分析工具假定指定的条件为真,即使不能静态证明它始终为真 以及: 在运行时,使用此方法相当于使用Assert(Boolean)方法 Requires将保证给定的谓词为true,如果静态代码分析器不能“
Contract.Requires(string.IsNullOrWhiteSpace(userName));
Contract.Assume(string.IsNullOrWhiteSpace(userName));
它只不同于设计时间/静态分析时间 合同。假设: 指示代码分析工具假定指定的条件为真,即使不能静态证明它始终为真 以及: 在运行时,使用此方法相当于使用Assert(Boolean)方法
Requires将保证给定的谓词为true,如果静态代码分析器不能“证明”事实并非如此,则可能会引发错误。根据合同。假设静态分析器将继续/发出警告/工具将决定的任何内容。想象您有这样一种方法:
bool ContainsAnX(string s)
{
return s.Contains("X");
}
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'.");
}
现在,如果将null
传递给该方法,则该方法将始终失败,因此您希望确保这种情况永远不会发生。这就是合同所要求的。它为方法设置了一个前提条件,该前提条件必须为true才能正确运行方法。在这种情况下,我们将:
bool ContainsAnX(string s)
{
Contract.Requires(s != null);
return s.Contains("X");
}
(注意:要求
并确保
必须始终位于方法的开头,因为它们是关于整个方法的信息。假设
用于代码本身,因为它是关于代码中该点的信息。)
现在,在调用方法“ContainsAnX”的代码中,必须确保字符串不为null。您的方法可能如下所示:
bool ContainsAnX(string s)
{
return s.Contains("X");
}
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(或者永远不应该返回null!)。在这种情况下,我们知道的比静态检查器知道的更多,因此我们可以告诉它假定变量永远不会为空:
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'.");
}
现在,使用静态检查器就可以了。如果启用了运行时契约,则在运行时也将检查该假定
您可能需要假设的另一种情况是,前提条件非常复杂,静态检查器很难证明它们。在这种情况下,您可以稍微推一下它,帮助它前进:)
就运行时行为而言,使用“假定”和“要求”之间没有太大区别。然而,使用静态检查器的结果会有很大的不同。在故障情况下谁对错误负责方面,每一项的含义也不同:
- Requires意味着调用此方法的代码必须确保条件成立
- 假设意味着此方法所做的假设应始终为真
- 是一个先决条件(“先决条件是通过使用Contract.Requires导出的”)李>
- 作为先决条件,将在方法调用时执行李>
- 不是先决条件,不是后决条件,不是不变量李>
- 在指定点执行李>
- “仅当定义了完整合同符号或调试符号时,才存在于生成中”李>