代码契约 - 假设与要求
这两种说法有什么区别?
Contract.Requires(string.IsNullOrWhiteSpace(userName));
Contract.Assume(string.IsNullOrWhiteSpace(userName));
What's the diference between these two statements ?
Contract.Requires(string.IsNullOrWhiteSpace(userName));
Contract.Assume(string.IsNullOrWhiteSpace(userName));
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
想象一下您有一个这样的方法:
现在,如果您将
null
传递给该方法,该方法将始终失败,因此您希望确保这种情况永远不会发生。这就是Contract.Requires
的用途。它为该方法设置了一个前提条件,该条件必须为真才能使该方法正确运行。在这种情况下,我们将:(注意:
Requires
和Ensures
必须始终位于方法的开头,因为它们是有关方法作为一个整体在代码本身中使用,因为它是有关代码中该点的信息。)现在,在调用方法“ContainsAnX”的代码中,您必须确保字符串不为空。您的方法可能如下所示:
这会正常工作,并且静态检查器可以证明
example
不为空。但是,您可能会调用外部库,这些库没有有关它们返回的值的任何信息(即它们不使用代码契约)。让我们改变一下这个例子:
如果
OtherLibrary
不使用代码契约,静态检查器会抱怨example
可能为空。也许他们的库文档说该方法永远不会返回 null(或者应该永远不会!)。在这种情况下,我们比静态检查器知道更多,因此我们可以告诉它
假设
变量永远不会为空:现在这对于静态检查器来说是可以的检查员。如果您启用了运行时合约,则还将在运行时检查假设。
您可能需要假设的另一种情况是当您的先决条件非常复杂并且静态检查器很难证明它们时。在这种情况下,您可以稍微推动它以帮助它前进:)
就运行时行为而言,使用 Assume 和 Requires 之间不会有太大区别。然而,静态检查器的结果会有很大差异。每个的含义也不同,就失败时谁对错误负责而言:
Imagine you have a method like this:
Now, this method will always fail if you pass
null
to it, so you want to ensure this never happens. This is whatContract.Requires
is for. It sets a precondition for the method, which must be true in order for the method to run correctly. In this case we would have:(Note:
Requires
andEnsures
must always be at the start of a method, as they are information about the method as a whole.Assume
is used in the code itself, as it is information about that point in the code.)Now, in your code that calls the method "ContainsAnX", you must ensure that the string is not null. Your method might look like this:
This will work fine, and the static checker can prove that
example
is not null.However, you might be calling into external libraries, which don't have any information about the values they return (i.e. they don't use Code Contracts). Let's change the example:
If the
OtherLibrary
doesn't use Code Contracts, the static checker will complain thatexample
might be null.Maybe their documentation for the library says that the method will never return null (or should never!). In this case, we know more than the static checker does, so we can tell it to
Assume
that the variable will never be null:Now this will be okay with the static checker. If you have runtime contracts enabled, the Assume will also be checked at run time.
Another case where you might need Assume is when your preconditions are very complex and the static checker is having a hard time proving them. In this case you can give it a bit of a nudge to help it along :)
In terms of runtime behavior there won't be much difference between using Assume and Requires. However, results with the static checker will differ greatly. The meaning of each is different as well, in terms of who is responsible for the error in case of failure:
它仅在设计时/静态分析时
合约上有所不同。假设:
“指示代码分析工具假设指定的条件为真,即使它无法静态证明始终为真”
和:
在运行时,使用此方法相当于使用 Assert(Boolean) 方法。
Contract.Requires 将保证给定的谓词为真,并且静态代码分析器如果无法“证明”情况并非如此,则可能会引发错误。根据合同。假设静态分析器将继续/发出警告/无论工具将决定什么。
It only differs design-time/static-analysis-time
Contract.Assume:
"Instructs code analysis tools to assume that the specified condition is true, even if it cannot be statically proven to always be true"
And:
At run time, using this method is equivalent to using the Assert(Boolean) method.
Contract.Requires will guarantee that the given predicate is true and static code analyzers might raise an error if they can't 'prove' that is not the case. On Contract.Assume the static analyzer will continue/issue a warning/whatever the tool will decide.
根据官方文档:第7页(前提条件)和11(假设)。
Requires:
假设:
According to official documentation: pages 7 (preconditions) and 11 (assumes).
Requires:
Assumes: