A good practice in software development is to define the interfaces of a module prior to the implementation of this module. Therefore you will normally begin to implement a class interface. Within this interface you define the class methods with their parameters and results.
With code contracts you can extend these method definitions and define the pre-conditions and post-conditions of class methods. Therefore, in my opinion, the creation of code contracts should also be done within the interface definition and not in the class implementation. Within this article I want to show you how you can add code contracts to class interfaces.
Example application
The example application is based on the application developed during the previous article of this series. The application contains a Person class with Name and Age properties. Furthermore the class contains an Initialize method to set up all properties. The following source code shows this application with the according code contracts.
static void Main(string[] args) { Person myPerson = new Person(); myPerson.Initialize("John Doe", -1); Console.ReadKey(); } public class Person { private string _name; private int _age; public string Name { get { return _name; } } public int Age { get { return _age; } } public Person() { _name = ""; _age = 0; } public void Initialize(string name, int age) { Contract.Requires(name != null); Contract.Requires(age >= 0); Contract.Ensures(Name == name); Contract.Ensures(Age == age); //init properties _name = name; _age = age; } [ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(Name != null); Contract.Invariant(Age >= 0); } }
Interface
At first we have to create the interface definition of the class. The following source code shows the implemented interface.
public interface IPerson { string Name { get; } int Age { get; } void Initialize(string name, int age); }
Contract class
It is not possible to add the code contracts to the interface. But it is possible to create a contract class and link it with the interface definition. To do this we have to create an abstract class which implements the interface. In this abstract class we now may implement all methods and their code contracts. At least we have to connect the class interface implementation with the abstract class containing the code contract implementation. The interface class must therefore be decorated with the ContractClass attribute and the code contracts class must be decorated with the ContractClassFor attribute. Now, whenever we use the interface, the contract is automatically applied. The following source code shows the according implementation.
[ContractClass(typeof(PersonContract))] public interface IPerson { string Name { get; } int Age { get; } void Initialize(string name, int age); } [ContractClassFor(typeof(IPerson))] public abstract class PersonContract : IPerson { public string Name { get { throw new NotImplementedException(); } } public int Age { get { throw new NotImplementedException(); } } public void Initialize(string name, int age) { Contract.Requires(name != null); Contract.Requires(age >= 0); Contract.Ensures(Name == name); Contract.Ensures(Age == age); } }
Class implementation and Invariants
After you have created the class interface and lined it with the code contract abstract class, you may implement you Person class. Of course, this class must be based on the according interface to connect it with the code contracts. But within the class you now don’t need to implement any contracts without one exception to this rule. Invariants must still be implemented in the concrete class and cannot be added to the abstract contract definition class. Invariants are internal implementation details and therefore they are contracts for the internal state of an object. Thus, it wouldn’t make sense to define invariants on an interface because interfaces are not a concrete implementation and therefore they have no internal state. The following source code shows the final implementation of the Person class. The invariant contracts are implemented in this class and all other contracts will be applied by using the according interface.
public class Person : IPerson { private string _name; private int _age; public string Name { get { return _name; } } public int Age { get { return _age; } } public Person() { _name = ""; _age = 0; } public void Initialize(string name, int age) { _name = name; _age = age; } [ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(Name != null); Contract.Invariant(Age >= 0); } }
Summary
By using interfaces and abstract code contract classes it is possible to split the definition of a class from its implementation. At the end, this results in higher-quality code.