Click here to Skip to main content
15,860,859 members
Articles / Programming Languages / C# 4.0

Introducing Code Contracts

Rate me:
Please Sign up or sign in to vote.
4.95/5 (83 votes)
25 Aug 2010CPOL3 min read 235.6K   713   186   93
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:

C#
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:

C#
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:

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

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

C#
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:

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

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

C#
[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:

C#
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:

C#
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:

C#
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)


Written By
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.

Comments and Discussions

 
QuestionMy Vote of 5 Pin
HobbyProggy22-Jun-15 22:11
professionalHobbyProggy22-Jun-15 22:11 
AnswerRe: My Vote of 5 Pin
Pete O'Hanlon22-Jun-15 22:20
subeditorPete O'Hanlon22-Jun-15 22:20 
GeneralRe: My Vote of 5 Pin
HobbyProggy22-Jun-15 22:38
professionalHobbyProggy22-Jun-15 22:38 
That does the trick, thanks a lot Smile | :)
if(this.signature != "")
{
    MessageBox.Show("This is my signature: " + Environment.NewLine + signature);
}
else
{
    MessageBox.Show("404-Signature not found");
}

GeneralRe: My Vote of 5 Pin
Pete O'Hanlon23-Jun-15 0:16
subeditorPete O'Hanlon23-Jun-15 0:16 
GeneralMy vote of 5 Pin
Member 374993825-Sep-13 11:22
Member 374993825-Sep-13 11:22 
GeneralMy vote of 5 Pin
Sperneder Patrick22-May-13 4:39
professionalSperneder Patrick22-May-13 4:39 
QuestionPostconditions Pin
Henning Dieterichs30-May-12 6:00
Henning Dieterichs30-May-12 6:00 
AnswerRe: Postconditions Pin
Pete O'Hanlon30-May-12 6:18
subeditorPete O'Hanlon30-May-12 6:18 
GeneralRe: Postconditions Pin
Henning Dieterichs30-May-12 6:53
Henning Dieterichs30-May-12 6:53 
GeneralRe: Postconditions Pin
Pete O'Hanlon30-May-12 6:59
subeditorPete O'Hanlon30-May-12 6:59 
GeneralMy vote of 5 Pin
Tim Corey30-May-12 4:50
professionalTim Corey30-May-12 4:50 
GeneralRe: My vote of 5 Pin
Pete O'Hanlon30-May-12 6:18
subeditorPete O'Hanlon30-May-12 6:18 
GeneralMy vote of 5 Pin
nico14424-May-12 5:04
nico14424-May-12 5:04 
GeneralMy vote of 5 Pin
Anurag Gandhi6-Sep-11 20:09
professionalAnurag Gandhi6-Sep-11 20:09 
QuestionMultiple inheritance style interfaces... Pin
c242328-Aug-11 1:10
c242328-Aug-11 1:10 
AnswerRe: Multiple inheritance style interfaces... Pin
Sentenryu24-Oct-12 23:31
Sentenryu24-Oct-12 23:31 
GeneralRe: Multiple inheritance style interfaces... Pin
c24232-Nov-12 11:24
c24232-Nov-12 11:24 
GeneralRe: Multiple inheritance style interfaces... Pin
Sentenryu4-Nov-12 22:30
Sentenryu4-Nov-12 22:30 
GeneralRe: Multiple inheritance style interfaces... Pin
c242315-Nov-12 3:32
c242315-Nov-12 3:32 
QuestionCouple of questions... Pin
Your Display Name Here17-Aug-11 13:04
Your Display Name Here17-Aug-11 13:04 
GeneralMy vote of 5 Pin
lewax0028-Jul-11 9:22
lewax0028-Jul-11 9:22 
GeneralMy vote of 5! Pin
Filip D'haene19-May-11 7:39
Filip D'haene19-May-11 7:39 
GeneralMy vote of 5 Pin
Fred van Lieshout1-May-11 20:21
Fred van Lieshout1-May-11 20:21 
GeneralMy vote of 5 Pin
hoernchenmeister27-Apr-11 1:26
hoernchenmeister27-Apr-11 1:26 
GeneralMy vote of 5 Pin
Jonathan Cardy22-Apr-11 23:50
Jonathan Cardy22-Apr-11 23:50 

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

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