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");
}
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);
}
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.
Now, if I call this method and pass in an invalid value (such as an Id
of 0
), I should trigger the contract failure:
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