Tags: , , | Categories: Articles, Labs Posted by RTomlinson on 8/19/2010 8:49 PM | Comments (0)

.NET 4.0 sees the introduction of Code Contracts. Code Contracts allow the developer to specify rules and "assumptions on your code in the form of pre-conditions, post-conditions and object invariants" (in the words of DevLabs). What this means in real terms is that we are able to apply contractual rules to methods or properties where typically we would have applied other input sanitizing methods.

Take, for example, an SMS messaging application where we have a dispatching service class. This class is responsible for sending out messages and contains a single Send method. A pre-condition to this method may be that the message length can only be 140 characters (as is typically the case). Code Contracts allows us to design our object and specify this contract as a condition to the method.

There are three ways to utilise this feature.

  1. Runtime Code Checking - Your code will be modified with the contracts at runtime and allows for runtime results.
  2. Static Code Analysis - A static checker that can check broken conditions and violations.
  3. Document Generation - Although I haven't used this facility, it is able to generate XML documentation.

I start by creating an interface for my message dispatcher that contains my single Send method.

   1:  using System.Diagnostics.Contracts;
   2:   
   3:  namespace CodeContractsFirstLook.Contracts
   4:  {
   5:      [ContractClass(typeof(MessageDispatcherServiceContract))]
   6:      public interface IMessageDispatcherService
   7:      {
   8:          bool Send(IMessage message);
   9:      }
  10:  }

As you can see this dispatcher service interface is attributed with the ConcreteClass attribute that is part of the System.Diagnostics.Contracts namespace. This tells the checker which contract class applies to the concrete class that implements this interface. Let's see what the contract class (MessageDispatcherServiceContract) looks like:

   1:  using System.Diagnostics.Contracts;
   2:   
   3:  namespace CodeContractsFirstLook.Contracts
   4:  {
   5:      [ContractClassFor(typeof(IMessageDispatcherService))]
   6:      public sealed class MessageDispatcherServiceContract : IMessageDispatcherService
   7:      {
   8:          bool IMessageDispatcherService.Send(IMessage message)
   9:          {
  10:              Contract.Requires(message.messageBody.Length < 140);
  11:              return default(bool);
  12:          }
  13:      }
  14:  }

Here the contract is specified on line 10. What we are saying here is that whenever a class implements the IMessageDispatcherService interface and the Send method is called we are going to evaluate the Requires method as a pre-condition to the method. In this case the condition is that the message body is less than 140 characters in length.

By default we must return something where the method siganture has a return type, otherwise our code won't compile. Here, I use the default keyword to return the default for the type bool.

Now let's take a look at the actual MessageDispatcherService that implements the IMessageDispatcherService interface and therefore will execute our interface contract:

   1:  using CodeContractsFirstLook.Contracts;
   2:   
   3:  namespace CodeContractsFirstLook
   4:  {
   5:      public class MessageDispatcherService : IMessageDispatcherService
   6:      {
   7:          public bool Send(IMessage message)
   8:          {
   9:              // It doesn't matter what we do here
  10:              // Our Contracts will be executed
  11:   
  12:              return true;
  13:          }
  14:      }
  15:  }

As our interface has a contract associated with it, whenever the method above is executed our contract code will execute to evaluate the message body length. We can test this code works with a simple console application.

   1:  using System;
   2:  using CodeContractsFirstLook.Messaging;
   3:  using CodeContractsFirstLook;
   4:   
   5:  namespace ConsoleApplication1
   6:  {
   7:      class Program
   8:      {
   9:          static void Main(string[] args)
  10:          {
  11:              var message = new SmsMessage();
  12:              var messageDispatcher = new MessageDispatcherService();
  13:   
  14:              message.messageBody = "This will certainly pass";
  15:              Console.WriteLine(string.Format("Was message dispatching successful? {0} ", 
  16:                  messageDispatcher.Send(message)));
  17:   
  18:              message.messageBody = "A very long message that surely must be over one hundred and forty characters by now...surely! Let me copy and paste into word to do a character count....a yes....we're good!";         
  19:              Console.WriteLine(string.Format("Was message dispatching successful? {0} ", 
  20:                  messageDispatcher.Send(message)));
  21:          }
  22:      }
  23:  }

Conclusion

In this post I've covered a very simplified overview of Code Contracts and a basic introduction as to how you can use the .NET 4.0 System.Diagnostics.Contracts to specify pre-conditions on methods, specifically using interface contracts.

This is very much the tip of the iceberg when it comes to the subject of Code Contracts.

One of the biggest benefits is the ability to ensure loose coupling of contracts from class code through interface contracts and the "Design-By-Contract" pattern seems a much neater implementation than the normal input sanitization/exception throwing mechanism that we typically deal with day-to-day.

What you need to get started

To get started you will need to download the Code Contracts project from DevLabs. This will add a "Code Contracts" panel to your projects properties (right-click on your project in Visual Studio and go to Properties). In order to perform runtime checks you will need to select the "Perform Runtime Contract Checking" option (see below):

Want to know more?

http://www.developer.com/net/article.php/3836626/Understanding-and-Benefiting-from-Code-Contracts-in-NET-40.htm

http://www.cauldwell.net/patrick/blog/CodeContracts.aspx

http://blogs.msdn.com/b/bclteam/archive/2008/11/11/introduction-to-code-contracts-melitta-andersen.aspx

http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx

 

Download my solution code sample:

CodeContractsFirstLook.zip (66.36 kb)