Click here to Skip to main content
Click here to Skip to main content

Introducing Code Contracts

, 25 Aug 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
Using Code Contracts to make elegant code

Introduction

How many times have you written methods where you end up bunging in a load of conditional tests up front to make sure that inputs are valid? You normally end up with a bunch of code that looks like this:

public void Initialize(string name, int id)
{
    if (string.IsNullOrEmpty(value))
        throw new ArgumentException("name");
    if (id < 0) 
        throw new ArgumentOutOfRangeException("id");
    // Do some work here.
}

While I applaud your diligence and true professionalism, doesn't code like this just smell awful to you? It certainly does to me, and it really seems to clutter methods up. Wouldn't it be great if we could set up some form of contract that mapped this out for us? Wouldn't it be nice if we had something that actually set up some pre and post conditions on the method calls? Wouldn't it be great if we had a Code Contract? Well, those nice people at Microsoft certainly think so and have helpfully provided us with the fruits of their labours based on their research in Spec#.

The Basics

Contracts basically fall into two categories; preconditions and postconditions. A precondition states that certain things must be true before a method can execute, and a postcondition states that certain things must be true after a method has executed. So far so good, and pretty handy.

Let's look at an example of this in operation:

public void Initialize(string name, int id)
{ 
    Contract.Requires(!string.IsNullOrEmpty(name));
    Contract.Requires(id > 0);
    Contract.Ensures(Name == name);
    Contract.Ensures(Id = id); 
    // Do some work here.
} 

This simple method has two preconditions (expressed using Contract.Requires) and two postconditions (expressed using Contract.Ensures). I like the clarity of the syntax here, it's clear that these form part of the contract (and Code Contracts can automatically create XML documentation directly from your code).

Some things that you should be aware of here; the contract must be specified before you attempt to do any work in the method; if you're not careful you don't get to choose what exception is thrown by the contract (you need to use the appropriate generic, e.g. Contract.Requires<ArgumentOutOfRangeException>); and you need to download a binary rewriter to actually use the contracts at runtime (called ccrewriter) from Dev Labs - it comes complete with a handy VS add in that makes working with ccrewriter a lot nicer; accessible from a really useful property page where you trigger ccrewriter by specifying that you want to perform runtime contract checking.

CodeContractsPropertyPage.png

Now, if I call this method and pass in an invalid value (such as an Id of 0), I should trigger the contract failure:

PreconditionExceptionInInterfaceContract.png

Now for the Useful Stuff

While this is all handy-dandy, there's so much more that Code Contracts can do. How about setting up an interface and having it so that the contracts are applied whenever you use the interface? Dagnabit, but that sounds good to me, and I bet it sounds good to anybody who's busy writing frameworks.

"Surely you jest Pete" I hear you say. I jest you not - this is easily achieved using Code Contracts, and here's how it's done. First of all, you define an interface. Let's set one up that we can use:

public interface IUseful
{ 
    void Initialize(string name, int id);
} 

Then we set up an abstract class that we use to actually define the contract:

public abstract class UsefulContract : IUseful
{ 
    public void Initialize(string name, int id)
    {
        Contract.Requires(!string.IsNullOrEmpty(name));
        Contract.Requires(id > 0);
        Contract.Ensures(Name == name);
        Contract.Ensures(Id = id);
    }
} 

Now, we need to decorate the interface to tell it that we have a class that forms the contract. We need to use the ContractClassAttribute attribute:

[ContractClass(typeof(UsefulContract))]
public interface IUseful

Then, we need to decorate the actual contract implementation to tie it back to the interface:

[ContractClassFor(typeof(IUseful))]
public abstract class UsefulContract : IUseful  

Now, whenever we use the interface, the contract is automatically applied.

What about Performance?

The beauty of Code Contracts is that they don't rely on reflection to perform their magic, the binary rewriter transforms the contract into runtime code. If we take a look at the code that we specify for the Name property in the attached sample project, we see it looks like this:

public string Name
{
    get
    {
        return _name;
    }
    set
    {
        if (_name == value) return;
        OnChanging("Name");
        _name = value;
        OnChanged("Name");
    }
}

The contract was set up in the contract class like this:

public string Name
{
    get
    {
        return string.Empty;
    }
    set
    {
        Contract.Requires(!string.IsNullOrEmpty(value), 
            "The name must be greater than 0 characters long.");
    }
}

Now, with the beauty of Code Contracts, this translates into the following runtime code:

public string Name
{ 
    get
    { 
        return this._name;
    }
    set
    {
        __ContractsRuntime.Requires(!string.IsNullOrEmpty(value), 
            "The name must be greater than 0 characters long.", 
            "!string.IsNullOrEmpty(value)");
        if (this._name != value)
        {
            this.OnChanging("Name");
            this._name = value;
            this.OnChanged("Name");
        }
    }
} 

Conclusion

I hope that I've whetted your appetite to go out and play with code contracts. The more I use them, the more I like them.

Part 2 of this article is now available here.

History

  • 23/08/10 - Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Pete O'Hanlon
CEO
United Kingdom United Kingdom
A developer for over 30 years, I've been lucky enough to write articles and applications for Code Project as well as the Intel Ultimate Coder - Going Perceptual challenge. I live in the North East of England with 2 wonderful daughters and a wonderful wife.
 
I am not the Stig, but I do wish I had Lotus Tuned Suspension.
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 5 PinmemberMember 374993825-Sep-13 12:22 
GeneralMy vote of 5 PinprofessionalSperneder Patrick22-May-13 5:39 
QuestionPostconditions PinmemberHenning Dieterichs30-May-12 7:00 
Hello!
 
Either I didn't understand postconditions or your comment "Do some work here" in your second code block is at the wrong line.
Shouldn't it be
public void Initialize(string name, int id)
{
    Contract.Requires(!string.IsNullOrEmpty(name));
    Contract.Requires(id > 0);
    // Do some work here.
    Contract.Ensures(Name == name);
    Contract.Ensures(Id = id);
}
?
 
Greetings,
Henning
If you find spelling- or grammer-mistakes, please let me know, so that I can correct them (at least for me) - english is not my first language...

AnswerRe: Postconditions PinprotectorPete O'Hanlon30-May-12 7:18 
GeneralRe: Postconditions PinmemberHenning Dieterichs30-May-12 7:53 
GeneralRe: Postconditions PinprotectorPete O'Hanlon30-May-12 7:59 
GeneralMy vote of 5 PinmemberTim Corey30-May-12 5:50 
GeneralRe: My vote of 5 PinprotectorPete O'Hanlon30-May-12 7:18 
GeneralMy vote of 5 Pinmembernico14424-May-12 6:04 
GeneralMy vote of 5 PinmemberAnurag Gandhi6-Sep-11 21:09 
QuestionMultiple inheritance style interfaces... Pinmemberc242328-Aug-11 2:10 
AnswerRe: Multiple inheritance style interfaces... PinmemberSentenryu25-Oct-12 0:31 
GeneralRe: Multiple inheritance style interfaces... Pinmemberc24232-Nov-12 12:24 
GeneralRe: Multiple inheritance style interfaces... PinmemberSentenryu4-Nov-12 23:30 
GeneralRe: Multiple inheritance style interfaces... Pinmemberc242315-Nov-12 4:32 
QuestionCouple of questions... Pinmemberxzz019517-Aug-11 14:04 
GeneralMy vote of 5 Pinmemberlewax0028-Jul-11 10:22 
GeneralMy vote of 5! PinmemberFilip D'haene19-May-11 8:39 
GeneralMy vote of 5 PinmemberFred van Lieshout1-May-11 21:21 
GeneralMy vote of 5 Pinmemberhoernchenmeister27-Apr-11 2:26 
GeneralMy vote of 5 PinmemberJonathan Cardy23-Apr-11 0:50 
GeneralMy vote of 5 PinmemberBigdeak12-Sep-10 22:11 
GeneralRe: My vote of 5 PinmvpPete O'Hanlon13-Sep-10 12:34 
GeneralMy vote of 5 PinmemberAbhinav S9-Sep-10 7:21 
GeneralRe: My vote of 5 PinmvpPete O'Hanlon13-Sep-10 12:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 25 Aug 2010
Article Copyright 2010 by Pete O'Hanlon
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid