21

I had overheard some discussion in my office recently about .Net "Contracts" however, when I asked some of my fellow employees, not of them could easily explain to me what they were for, or what they even were.

Does anyone have any resources, explanations, and perhaps a tutorial on their usage?

Thanks,

Paul

Paul Gleeson
  • 438
  • 4
  • 10
  • If someone is thinking about using Code Contracts in 2019, you might reconsider. terrajobst (of Microsoft, I think) wrote on August 3, 2018, "We have stopped investing in code contracts a while ago. We've added it to .NET Core 2.0 as part of our compatibility effort, but I wouldn't recommend new code using it." This was copied from the comments section at the bottom of https://learn.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts. – Mike Grove aka Theophilus Jan 03 '19 at 15:07
  • This is a correction to my last comment. The quote came from the Closed tab in the Feedback section at the bottom of the URL that was provided. The URL to that section is https://learn.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts#feedback. – Mike Grove aka Theophilus Jan 03 '19 at 15:45
  • That discussion link is https://github.com/dotnet/docs/issues/6361 for more discussion and https://github.com/dotnet/corefx/issues/24681 is another relevant link regarding code contracts being phased out, quote "_Most of Contract's static analysis is better served by Roslyn Analysers anyway, or C#8's Nullable Reference Types._". – Andy Brown Jul 12 '19 at 12:35

2 Answers2

25

Code Contracts were introduced in .NET 4.0 and they provide a language-agnostic method to express coding assumptions in programs.

They basically allow you to check for pre-conditions, post-conditions and other features and can greatly improve the testing process and the eventual quality of code that is being written.

From Microsoft:  

  • Runtime Checking. Our binary rewriter modifies a program by injecting    the contracts, which are checked as part of program> execution. Rewritten programs improve testability: each contract acts as an oracle, giving a test run a pass/fail indication. Automatic testing tools, such as Pex, take advantage of contracts to generate more meaningful unit tests by filtering out meaningless test arguments that don't satisfy the pre-conditions. 

  • Static Checking. Our static checker can decide if there are any contract violations without even running the program! It checks for implicit contracts, such as null    dereferences and array bounds, as well as the explicit contracts.

  • Documentation Generation. Our documentation generator augments existing XML doc files with contract information. There are also new style sheets that can be used with Sandcastle so that the generated documentation pages have contract sections.

Learn More:

Rion Williams
  • 74,820
  • 37
  • 200
  • 327
17

Code Contracts are a relatively new way of performing checks on input and output of functions. Where they differ from your standard Assert type checking is that the generated IL that checks input checks it directly prior to the function being called, and the code that checks output, after your function has actually exited.

Why is this useful?

Well, it prevents you modifying the variables after you think your function may return, thereby potentially introducing bugs.

Here's an example.

public void doSomething(SomeObject foo)
{
    Contract.Requires<ArgumentNullException>(foo != null);
}

Now, Code Contracts require that there be no code before that check. In the generated IL, the value of foo is tested PRIOR to the call. It's a sure-fire way of ensuring that your input is as expected.

The other, is the Contract.Ensures construct. This is basically like Requires but operates on your return value.

public int doSomethingElse()
{
    Contract.Ensures(Contract.Result<int>() != 0);
    int ret = 1;
    return ret;
}

This would be particularly useful if you had multiple exit paths from your function...

public int someBadFunction()
{
    Contract.Ensures(Contract.Result<int>() != 0);
    if(....)
    {
       if(....) return 2;
       if(....) return 8;
    }
    return 3;
}
Moo-Juice
  • 38,257
  • 10
  • 78
  • 128