35

What's the diference between these two statements ?

Contract.Requires(string.IsNullOrWhiteSpace(userName));

Contract.Assume(string.IsNullOrWhiteSpace(userName));
user137348
  • 9,610
  • 17
  • 62
  • 88

3 Answers3

68

Imagine you have a method like this:

bool ContainsAnX(string s)
{
    return s.Contains("X");
}

Now, this method will always fail if you pass null to it, so you want to ensure this never happens. This is what Contract.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:

bool ContainsAnX(string s)
{
    Contract.Requires(s != null);

    return s.Contains("X");
}   

(Note: Requires and Ensures 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:

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

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:

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

If the OtherLibrary doesn't use Code Contracts, the static checker will complain that example 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:

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

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:

  • Requires means that the code which calls this method must ensure the condition holds.
  • Assume means that this method is making an assumption which should always hold true.
porges
  • 28,750
  • 3
  • 83
  • 112
  • Very nice explanation! But one question. What have you meant by "static checker". I'm using VS Professional edition. – user137348 Jan 24 '11 at 09:49
  • 2
    The static checker is a program that tries to verify that all the contracts are true at compile time. Unfortunately it's only available with VS2010 Premium or Ultimate edition at the moment. – porges Jan 24 '11 at 20:38
  • 2
    The static checker is now available for all levels of Visual Studio (barring Express, of course). – porges Mar 19 '12 at 20:26
3

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.

rene
  • 37,946
  • 78
  • 99
  • 132
0

According to official documentation: pages 7 (preconditions) and 11 (assumes).

Requires:

  • Is a precondition ("preconditions are extressed by using Contract.Requires");
  • As a precondition will be executed on method invoke;

Assumes:

  • Not a precondition, not a postcondition, not an invariant;
  • Is executed at the point where it is specified;
  • p. 11 "Exist in a build only when the full-contract symbol or DEBUG symbol is defined";
Anton Lyhin
  • 1,817
  • 2
  • 26
  • 33