Introducing Code Contracts for .Net 4.0

One of the new features of .Net 4.0 is code contracts. Code contracts are a way for programmers to define how methods and classes should behave in a more complex way then simply their signature. A contract for example could specify that a methods parameters should not be null, or that the value it returns should always be positive.

Code contracts themselves are broken into two parts. The library itself which is included in .Net 4.0 and the Visual Studio addon (downloaded here). The two need to be paired together to do useful work (though no doubt third parties will introduce their own products in the future).

Code Contracts do two things. Firstly they replace existing contract code of the mode:

public static int Divide(int number, int divisor)
{
    if (divisor == 0) throw new Exception();

With:

public static int Divide(int number, int divisor)
{
	Contract.Requires(divisor != 0);

Obviously a slightly nicer syntax isn't going to convince many people to change their patterns. No the real meat comes with static analysis. Static analysis allows Code Contracts to examine your code at compile time and attempt to determine if your code obeys the contracts specified. Static analysis is only available with the "Premium Edition" (free but only runs on Visual Studio 2008 Team System, Visual Studio 2010 Premium Edition, or Visual Studio 2010 Ultimate Edition).

To enable static analysis you must install Code Contracts Premium, and in the Properties of your Project enable Perform Static Contract Checking. When you do a compile you will start to get warnings. Lets look at some examples.

public static double Divide(int number, int divisor)
{
	Contract.Requires(divisor > 0);

	return number / divisor;
}

In the above (trivial) method we want to ensure that the divisor is never a negative number, and that we never encounter a divide by zero error. If we then make the two following calls:

 Divide(1, 2);
 Divide(1, 0);

When we compile we get a nice blue squiggly line under our second call to divide, along with the following error:

Warning	1	CodeContracts: requires is false: divisor > 0	


This works pretty nicely, lets try something more complex:

 public static void TestCodeContract(int value)
{
	TestLimits(105);
	TestLimits(95);
	TestLimits(115);
}

public static void TestLimits(int i)
{
	 Contract.Requires(i > 100);
	 Contract.Requires(i < 110);

	//Do Something
}

As expected we get errors for the values 95 and 105.

Warning	1	CodeContracts: requires is false: i > 100	
Warning	1	CodeContracts: requires is false: i < 110	


Puzzlingly only one error shows, the second remains hidden until the first is resolved. What happens when rather than hardcoding an example we pass in a variable?

 public static void TestCodeContract(int value)
{
	TestLimits(value); 
}

Warning	3	CodeContracts: requires unproven: i > 100	
Warning	5	CodeContracts: requires unproven: i < 110	


Which we can resolve by including a check:

public static void TestCodeContract(int value)
{
	if(value > 100 && value < 110)
		TestLimits(value); 
}

So that's pretty solid, we can write contracts, and the static analysis will give us a good idea if there are any problems. We can also use Code Contracts to specify rules for the return value using Contract.Ensures(), as well as object invariants which are rules that should always be true for an object using Contract.Invariant().

This is all great but who is it useful for? The answer is any large team using a well-designed interface. Currently you would either use exceptions which are only useful at runtime, or documentation, which let’s face it is unlikely to be read when 4 years on the maintenance programmer makes a change 3 functions up the call stack. Care is going to be needed though. It looks like it would be very easy to begin burying business logic in your contracts, or hardcoding values. A project where the specifications are more fluid is likely to lead to a lot of pain if the contracts are constantly being revised.

It's not all roses however. The static analyser seems more like a beta product then anything. It had problems with int? and the warnings produced where often unhelpfull. Still you can use the Code Contracts library right now; undoubtedly the Static analysis will continue to evolve.

All in all this looks like a pretty nice addition to .Net 4.0. You can read far more about it here.

Created at: Monday, March 29, 2010 Last edited at: Wednesday, March 31, 2010

Tagged: