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:
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");
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:
Precondition
: Refer to the things it expect to do Postcondition
: Refer to things that it guarantees to do 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
.
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");
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:
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:
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");
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:
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:
[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.
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
.
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.
Contract.Exists
/ ForAll
: Expresses constraint for a collection OldValue
/ Result
: Gets you the OldValue
or ReturnValue
before the code gets executed:
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:
[ContractClass(typeof(HumanContract))]
public interface IHuman
{
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
.
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.