Click here to Skip to main content
15,881,204 members
Articles / Programming Languages / C#

Code Contracts in .NET 4.0 & its Internals

Rate me:
Please Sign up or sign in to vote.
4.93/5 (7 votes)
13 Feb 2011CPOL11 min read 31.2K   8   9
Code Contracts in .NET 4.0 & its Internals

After I have introduced the Internals of Exception handling, I mentioned that I will cover some of the features that are coming as an improvement to it. Code Contract in .NET 4.0 is one among them. In this post, I will cover how you could use code contract in your application and also take the way through to its internals later on.

One can argue with me that code contract is a part of unit testing and might be included as a part of .NET test projects, but according to me, it is not restricted only for testing frameworks, you could use it more likely for your own libraries so that you could have better code handling and also some way of separation between the validation logic for which the library is built in and how you would react with the outside world. Now let us discuss how to use it in your program, and later on I will build an application to use it.

The Basis

As an application developer, it is our duty to validate any input to a program from an external agent. Most of us spend a lot of time while developing custom validation blocks which might look for a condition and throw an exception with a custom message. But is it actually worth it. Putting this kind of unnecessary validation block for every method literally makes it look ugly and hard to maintain. Say for instance, I want to write a custom method which might input two parameters from external agent and process it:

C#
public void OfferMeValues(string arg1, string arg2)
{
    if (arg1 == null)
        throw new ArgumentNullException("Argument cannot be null, Parameter Name: arg1");
    if (arg2 == null)
        throw new ArgumentNullException("Argument cannot be null, Parameter Name: arg2");

    if (arg1.Trim().Length == 0 || arg2.Trim().Length == 0)
        throw new ArgumentException("No argument cannot be empty or whitespace");

    if (arg1.Equals(arg2))
        throw new ArgumentOutOfRangeException
	("Cannot work on identical parameters, Parameter : arg1, arg2");

    //here goes your actual logic

    Console.WriteLine("We ensure objects are not null, not empty and not equal");
}

This looks horrible, right. Even though the entire method has only one single line of code with Console.WriteLine, the entire validation block resides just above it. Yes it is possible to move it somewhere, may be you can build one utility kind of class which takes care of these validations, but yet each method will have its own kind of validation. Hence, you need to create your own library and call it from every method. Well, .NET code contracts addresses the issue. It writes the code for you during runtime, not even giving a standard library to handle these, but also makes your validation instructions available before any code. One of the major advantages of Code contract is that your assembly will hold each of these validation entries internally within the block, if not it calls the Code Contract library and also allows you to write static checking on these during compilation.

Installation

Code contract library actually resides directly into BCL with .NET 4.0. The compiler is also updated to write these adjustments for you. Installation is only needed to have static type checking from your Visual Studio. To have that, please download the installer from DevLabs Link and install it to your machine. Once you successfully install, create a new project on your Visual Studio, and you will get a new Tab in properties section to configure your code contract with MsBuild.

You can also go to Microsoft research site on Code Contract to know more about it.

.NET code contract follows design principle of Design By Contract. This principle have 3 tenets which code contract also takes care of:

  1. Precondition: Refer to the things it expect to do
  2. Postcondition: Refer to things that it guarantees to do
  3. Invariant: Refer to things it maintains

Well, the tenets are fine for Design by Contract and .NET code contract follows each of the tenets properly. We will examine each of them in this article.

Precondition

The example that I gave just above holds the strong base on preconditions. Precondition means the things you need to satisfy before running the code. Hence if precondition is failed, no other line inside the method gets executed.

Contract.Requires allows you to pass a condition and a message so that it throws an exception whenever the condition fails to satisfy. As Requires ensures that exception occurs beforehand, it is treated as Precondition. Let me rewrite the code that I specified above with Requires.

C#
public void OfferMeValues(string arg1, string arg2)
{
    Contract.Requires<ArgumentNullException>(arg1 != null, 
		"Argument cannot be null, Parameter Name: arg1");
    Contract.Requires<ArgumentNullException>(arg2 != null, 
		"Argument cannot be null, Parameter Name: arg2");
    Contract.Requires<ArgumentException>(arg1.Trim().Length > 0 && 
		arg2.Trim().Length > 0, "No argument can be empty");
    Contract.Requires<ArgumentOutOfRangeException>(!arg1.Equals(arg2), 
		"Cannot work on identical parameters, Parameter : arg1, arg2");

            
    //here goes your actual logic

    Console.WriteLine("We ensure objects are not null, not empty and not equal");
}

Hmm, doesn’t it look good on me? Yes, using code contract method makes it much more cleaner and easy to read. Hence when arg1!=null, it throws ArgumentNullException with the custom message provided.

Now if you try to run your application with:

C#
ContractInvoker invoker = new ContractInvoker();
invoker.OfferMeValues(null, null);

where CotractInvoker is our class, you will get something like this:

This is weird. Now after I read the documentation, I found that PreCondition with exception can only be used when runtime checking is enabled. It says "If you are using scenario 2 (Requires (Exn)) and you make your source code available to other developers, you might want to alert them that they need to use the tools to build your source". Hence it puts the messagebox or rather a Debug.Asset statement to make sure the project is built only using runtime checks turned on.

Hence, if I change the AssemblyMode to standard, which eventually rewrites the IL instructions during compilation, you will get through the exception.

Now if I rerun the application, it throws the exception correctly.

If you try to see what happened inside the assembly after the tool builds it, you will find exactly what you are looking for. The method looks like :

The __ContractRuntime is a class that is automatically added to the assembly that takes care of your calls.

Hmm, the Requires eventually calls upon ContractHelper.RaiseContractFailedEvent, but later on throws the exception which we have wanted:

The exception message comes after the string Precondition failed :arg1!=null.

PostCondition

Postcondition runs your code and throws the exception after it successfully executes it. Contract.Ensures lets you define a Postcondition for your application. The Code contract tool adds up your required code to deal with the post condition. If I change the code a little bit, it will look like:

C#
public void OfferMeValues(string arg1, string arg2)
{
    Contract.Requires<ArgumentNullException>(arg1 != null, "arg1 cannot be null");
    Contract.Requires<ArgumentNullException>(arg2 != null, "arg2 cannot be null");
    Contract.Ensures(arg1.Trim().Length > 0 && arg2.Trim().Length > 0, 
		"No argument can be empty");
    Contract.Ensures(!arg1.Equals(arg2), 
	"Cannot work on identical parameters, Parameter : arg1, arg2");

            
    //here goes your actual logic

    Console.WriteLine("We ensure objects are not null, not empty and not equal");
}

Now as static checker is turned on, I generate the exception at runtime just by changing the code a little:

C#
ContractInvoker invoker = new ContractInvoker();
string x = Console.ReadLine();
string y = Console.ReadLine();
invoker.OfferMeValues(x, y);

Now if I put same string for both the inputs, it will throw you the exception as supposed.

First of all I should notify in this, that Contact.Old(arg1) is just a string variable. So beware of this while you see the internal code. So first it calls the Preconditions that I applied in the same way as demonstrated earlier. It loads them to the string variable. Notice, every assignment is put inside try/catch block (may be this is because it doesn’t know if cast is valid or not). But I doubt if this try/catch is required, may be it could automatically throw the exception if cast is invalid. What do you think?

Finally it calls upon __ContractRuntime.Ensures to run your post conditions.

The __ContractRuntime.Ensures looks like:

So it’s the same code.

Invariants

Well, so far as we understand, Precondition and PostCondition works only when there is a caller for the program. Invariant works little differently. Invariants are special conditions which should evaluate to true before and after the execution of the code. Hence it ensures that the object will follow the conditions even if you have subtypes of it, you have overridden methods, for every method block like properties, events, methods, etc. Hence Invariants ensures that there will never be a situation for the entire object where the condition fails.

To work with invariants, you need to create a method which infers the conditions. Let's create one:

C#
[ContractInvariantMethod]
private void ContractInvariant()
{
    Contract.Invariant(!this.Argument1.Equals(this.Argument2), 
	"Cannot work on identical parameters, Parameter : arg1, arg2");
}

Here you should note ContractInvariantMethod is a special attribute that designates the method to be holding Invariant conditions. You are not allowed to write anything other than Contract.Invariant sequence in this method. If you do, you will be shown an error message:

Now if you put a breakpoint on the Invariance method, you will see that the method will be called as soon as you are about to create the object. Now let me check the Reflector to see what it writes for us.

Hence you can see, for every call to any method inside the block, the contract ensures that the Invariant condition is satisfied. The invariant method sets #evaluatingInvariant$ to false only if the object contract fails. Similar to others, __ContractsRuntime.Invariant will report you the failure.

Static Checker

Well, as far as we have discussed, Code contract ensures that your condition is satisfied before running the code. Now you might be thinking, you can do this even with some static utility methods. What makes it so different?

The difference lies in the static checker. Visual Studio builds a special assertion statement that ensures each contracts are true even before running the actual code. So even though you are not evaluating the actual code, you can get warnings on where the exceptions might occur while you build the application.

Static Checker ensures that every possible way of calling the code satisfies the conditions. Let me show you how you can enable static checker. Go to properties panel of the project and check Perform Static Contract Checking checkbox.

Once you enable the static checker, the MSBuild will invoke the contract assertions before building the project. You can see the warnings put in the warning pane which lets you detect which contracts might be failed during the process.

You can see a number of warnings placed on the pane which is provided by the static checker.

Some Other Methods

We have already understood about Ensures, Requires and Invariant methods. Now let me try few other methods available with Code contract.

  1. Contract.Assume: It gives you a chance to make an assumption to the static checker that the condition is satisfied. Contract.Assume can be used anywhere in the code in comparison to Requires or Ensures that might be used only to the beginning of the block. Contract.Assume checks at an intermediate point of the code before calling a method that explicitly defines the Contract.

    C#
    string x = Console.ReadLine();
    string y = Console.ReadLine();
    Contract.Assume(x != null);
    Contract.Assume(y != null);
    invoker.OfferMeValues(x, y);

    This will ensure that the invoker.OfferMeValues will never be null to the static checker even though the values are coming from a method which never uses a contract.

  2. Contract.Exists / ForAll: Expresses constraint for a collection
  3. OldValue / Result: Gets you the OldValue or ReturnValue before the code gets executed:

    C#
    public int CurrentValue {get;set;}
    public void IncrementBy(int value)
    {
        Contract.Ensures(this.CurrentValue == 
    		Contract.OldValue<int>(this.CurrentValue) + value);
        this.CurrentValue += value;
    }

    Here the oldValue can be retrieved from Contract.OldValue, so that it ensures that the value is always valid for the block.

    There are also a few other methods which are used very rarely.

Contracts for Interfaces

Well, you are not restricted to write contracts only for a well defined class. Many of us like me, who write libraries can use interface and add Contract to that interface beforehand for the library. Let's see how you can do this:

C#
[ContractClass(typeof(HumanContract))]
public interface IHuman
{
    //Lets make Name a mandatory
    string Name { get; set; }

    int Age { get; set; }

    void GreetMe();
}

[ContractClassFor(typeof(IHuman))]
public abstract class HumanContract : IHuman
{
    #region IHuman Members

    public abstract string Name { get; set; }
    public abstract int Age { get; set; }

    public void GreetMe()
    {
        Contract.Ensures(!string.IsNullOrEmpty(this.Name));
        Contract.Ensures(this.Age > 0);
        Contract.Ensures(this.Age < 100);            
    }

    #endregion
}

Here, we want our interface IHuman to ensure a contract that Name cannot be null or empty and Age should be between 1 to 99. We use an abstract implementation of the interface to define the Contract. ContractClass lets you define the type of the Contract class and ContractClassFor defines the type of the interface.

Hence when we create a concrete type from IHuman, the method will automatically get the contract from the buddy class.

Now, if you try to see what happens through Reflector, you will see there is no existence of HumanContract type rather the class which implements the interface IHuman automatically gets the contracts from HumanContract.

C#
public class People : IHuman
{
    public People(string name, int age)
    {
        this.Name = name;
        this.Age = age;
    }
    #region IHuman Members

    public string Name
    {
        get;
        set;
    }

    public int Age
    {
        get;
        set;
    }

    public void GreetMe()
    {
        Console.WriteLine("Hi {0}, Your age is {1}", this.Name, this.Age);
    }

    #endregion
}

Now the People class will look like:

The contract will be automatically put from the Contract we define in HumanContract abstract class.

When It Comes in Terms of Performance?

This might come to your mind, that even though we have a concrete Code Contract feature, can we turn off the feature when it is ported at runtime. Well, I must not recommend you to disable runtime checking, but if you are using an application for end user (not a library) and ensure that everything is ok, you can turn off Runtime Checking before releasing the code. This will help you performance gain, even though you can still get warnings from Static Checker. To turn off the Runtime checking, go to Properties again and uncheck "Perform Runtime Checking" checkbox.

This will ensure that the assembly will not hold any runtime Contracts.

FAQ on Code contracts.

Conclusion

Code contract is one of the major improvements to the .NET library. In spite of normal exception handling and validation of code, it enables you to put your logic way above the abstraction level. It lets you define your own code contract and ensure that the contract satisfied even before the actual exception occurs. The Static Checker helps to assert conditions before the actual execution of code thereby preventing you to have any runtime exception.

You can download the sample code from here.

I hope most of you will use this lovely feature.

Thanks for reading.

License

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


Written By
President
India India
Did you like his post?

Oh, lets go a bit further to know him better.
Visit his Website : www.abhisheksur.com to know more about Abhishek.

Abhishek also authored a book on .NET 4.5 Features and recommends you to read it, you will learn a lot from it.
http://bit.ly/EXPERTCookBook

Basically he is from India, who loves to explore the .NET world. He loves to code and in his leisure you always find him talking about technical stuffs.

Working as a VP product of APPSeCONNECT, an integration platform of future, he does all sort of innovation around the product.

Have any problem? Write to him in his Forum.

You can also mail him directly to abhi2434@yahoo.com

Want a Coder like him for your project?
Drop him a mail to contact@abhisheksur.com

Visit His Blog

Dotnet Tricks and Tips



Dont forget to vote or share your comments about his Writing

Comments and Discussions

 
Generalthis how i got healed Pin
Dolson Albert2-Dec-13 21:36
Dolson Albert2-Dec-13 21:36 
GeneralPostConditions are PreConditions Pin
Crawfis22-Feb-11 3:38
Crawfis22-Feb-11 3:38 
GeneralRe: PostConditions are PreConditions Pin
Pete O'Hanlon22-Feb-11 9:55
mvePete O'Hanlon22-Feb-11 9:55 
GeneralMy vote of 3 Pin
Crawfis22-Feb-11 3:36
Crawfis22-Feb-11 3:36 
GeneralInteresting - my vote of 5 Pin
Pete O'Hanlon15-Feb-11 9:28
mvePete O'Hanlon15-Feb-11 9:28 
GeneralRe: Interesting - my vote of 5 Pin
Abhishek Sur20-Feb-11 6:36
professionalAbhishek Sur20-Feb-11 6:36 
GeneralRe: Interesting - my vote of 5 Pin
Pete O'Hanlon22-Feb-11 10:17
mvePete O'Hanlon22-Feb-11 10:17 
GeneralMy vote of 5 Pin
Kunal Chowdhury «IN»13-Feb-11 23:15
professionalKunal Chowdhury «IN»13-Feb-11 23:15 
GeneralRe: My vote of 5 Pin
Abhishek Sur13-Feb-11 23:16
professionalAbhishek Sur13-Feb-11 23:16 

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.