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

New .NET Feature - Code Contracts

By , 12 Aug 2009
 

Introduction

.NET 4.0 is just around the corner and many new features are making their presence felt. One such feature is related to the quality of .NET code. This functionality just looks like a cool wrapper for Debug.Assert. But exploring details helped me understanding its power. [And hence, I guess, I am writing this article.]

If you prefer to watch this demo on video – then check out this channel 9 clip. Code contract bits can be downloaded from here and it works with VS 2008 standard and TS edition.

Ok – so after you install the bits – fireup VS 2008 and create a new console application. Add a reference to the Microsoft.Contracts library as shown below and insert:

using System.Diagnostics.Contracts 

and

using System.Diagnostics 

at the top of your program.

ref.JPG

Just so we understand it clearly – let's write a class SimpleCalculate and use our old friend Debug.Assert to code defensively.

    class SimpleCalculate
    {
        private int num1;
        private int num2;

        public SimpleCalculate(int numberone, int numbertwo)
        {
            num1 = numberone;
            num2 = numbertwo; 
        }

        public int Divide()
        {
            Debug.Assert(num2 > 0, "numbertwo should be greater than 0"); 
            if (num2 > 0)
                return num1 / num2;

            return num1;
        }
    }

And our console app will look like:

class Program
    {
        static void Main()
        {
            SimpleCalculate sc = new SimpleCalculate(4, 0);
            Console.WriteLine("Result is {0}", sc.Divide());
            Console.ReadLine(); 
        }
    }

If we run this code – big surprise – Debug.Assert will fire [if you build the project in debug mode] and will populate the following window:

debugassert.JPG

Fine – this is a good enough solution. So why do we need anything else. Let’s rewrite the same class with code contracts.

class ClaculateWithContracts
    {
        private int num1;
        private int num2;

        public ClaculateWithContracts(int numberone, int numbertwo)
        {
            num1 = numberone;
            num2 = numbertwo; 
        }

        public int Divide()
        {
            Contract.Requires(num2 > 0); 
            if (num2 > 0)
                return num1 / num2;

            return num1;
        }
    }

So if you run this code as:

ClaculateWithContracts cc = new ClaculateWithContracts(4, 0); 

Console.WriteLine("Result is {0}", cc.Divide()); 

Nothing will happen. In fact, because of the high quality of my code – output will be 4. [i.e. this code will not break – that’s why I am an architect – I can write unbreakable code. Figure out why the output is 4.]

The reason our contract is not working is because we need an additional step to use this contract. Right click on the project and go to the properties as shown below:

properties.JPG

And from properties window, select Code Contract and check the perform runtime contract checking checkbox as shown below:

addcontract.JPG

Now if you run the code again, our contract will hit. It will produce the following output:

contractassertion.JPG

Not much different than what Debug.Assert did – correct? But wait a minute before you close the browser window... let me finish the story here. One important thing to notice is the timing when the assertion window is produced. Debug.Assert will hit when you reach up to that condition, whereas  pre condition failed window is populated as soon as ClaculateWithContracts cc = new ClaculateWithContracts(4, 0); line is executed. You can check the call stack to confirm this claim.

Now the thing that sucks the most is that contract static checking is only available in VSTS, and I am using VS 2008 pro SP1. So I can't talk about that feature here. But it is a great way to harden your code.

Now a little bit of decoupling – comment out the line Contract.Requires(num2 > 0); and add a special method – just type cim and VS code snippet will show up – hit the tab twice to insert the boiler plate code.

[ContractInvariantMethod]
 protected void ObjectInvariant()
 {
   Contract.Invariant(this.num2>0);
 }

Now if you run the program, you will get the following output:

conditionassertion.JPG

So by doing this, we opened up a communication channel for ClaculateWithContracts to express what is acceptable and what is not acceptable for it to work with. Again, if you trace the call stack – this window will pop up at the time of the instantiation of ClaculateWithContracts.

Ok – you are still not convinced that this is any better than Debug.Assert. So let's add one more thing – a money back guarantee that our method will always behave and will do the right thing and nothing else – all the time. WOW – what a baloney! Am I smoking something – I mean if the code will work right 100% of the time, then where is the job security? [if (U.MyBoss) please ignore; else continue;]

Anyways, we can add a guarantee that our method will always return a non-zero result. Let's modify our method to implement this functionality. 

  public int Divide()
        {
            Contract.Ensures(Contract.Result<int />() > 0); 
            if (num2 > 0)
                return num1 / num2;

            return num1;
        }

Notice the Contract.Ensures, it means the result coming out of this method will always be greater than 0. Just press ce to insert Contract.Ensures snippet and inside it type crr to insert the contract result snippet. So now we have two way traffic – ClaculateWithContracts is very clear about what is acceptable and what its public methods will do. So if you call this type as:

ClaculateWithContracts cc = new ClaculateWithContracts(4, 8); 

you will get a message like the one shown below explaining the postcondition failure:

postconditionassertion.JPG

Now for those who are paying close attention to this implementation – we have Contract.Ensures(Contract.Result<int>() > 0); before the return statement and in fact the actual logic. So how does this contract work? I mean, if the logic is still not executed then how come this code is evaluating the end result? Magic – not at all.

You have reached upto this point only proves your determination to learn new technology. So please go ahead and figure out this last missing link. Let me know the answer on 1800 call abhi!

Happy programming!

History

  • 12th August, 2009: Initial post

License

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

About the Author

abhigad
Architect ZimbaTech Solutions
United States United States
Member
MS Computer Science + Information Science
Consulting + Software Development
Blog: Profile

Company: ZimbaTech Solutions
abhijit gadkari
abhijit dot gadkari at gmail dot com
Santa Ana,CA-92705

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralNew .NET Featuremembercandyford14 Jan '11 - 0:18 
GeneralMy vote of 1memberlouthy18 Aug '09 - 5:07 
QuestionAny way to use automated tools for contracts?membersupercat913 Aug '09 - 6:16 
AnswerRe: Any way to use automated tools for contracts?memberarepetti7714 Aug '09 - 1:41 
GeneralRe: Any way to use automated tools for contracts?membersupercat914 Aug '09 - 4:59 
GeneralRe: Any way to use automated tools for contracts?memberabhigad14 Aug '09 - 5:11 

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 12 Aug 2009
Article Copyright 2009 by abhigad
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid