.net-4.0 - 代码契约(Contract) - 假设与要求

标签 .net-4.0 code-contracts

这两种说法有什么区别?

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");
}   

( 注意 : RequiresEnsures 必须始终位于方法的开头,因为它们是有关整个方法的信息。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/

    相关文章:

    C# .Net 4.0 控制台应用程序 - 如何在所有线程完成之前保持事件状态?

    php - PHP 中的契约式编程

    c# - 让代码契约在 Visual Studio 2010 中工作

    c# - Contract.Requires 抛出 pex 错误

    .net-4.0 - 为什么 ccrewrite.exe 没有从命令行执行任何操作?

    c# - System.MissingMethodException Int32 System.Environment。 get_CurrentManagedThreadId() 方法

    c# - 使用 caliburn micro 设置 RadioButton Checked in code

    .net - 为什么 System.Environment.MachineName 值大写?

    wpf - .net 4 中的 MVVM 有什么新功能?

    .net-4.0 - 我可以在对象不变量的代码中自由到什么程度?