Code contracts offer an easy way to define the pre-conditions and post-conditions for methods. If you create different methods it may happen that the same contracts are used multiple times, especially in overloaded methods with similar parameters.
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.
Contract abbreviator
The example application contains the following method with two pre-conditions.
public void Initialize(string name, int age) { Contract.Requires<ArgumentNullException>(name != null); Contract.Requires<ArgumentOutOfRangeException>(age >= 0); Contract.Ensures(Name == name); Contract.Ensures(Age == age); //init properties _name = name; _age = age; }
Let’s say you want to implement new functionality and add an additional (optional) address for the person. So you create a second Initialize method with name, age and address parameters. Within this method you have to create the same code contracts again to check name and age. According to the “don’t repeat yourself” implementation practice it would be good style to create only one check which can be reused in both methods. This can be implemented by using contract abbreviators.
First of all you have to create a private method and add the ContractAbbreviator attribute to the method. Then you can write your code contracts within this method. At least you can use this abbreviator method instead of your code contracts in the other methods. The following source code shows the adapted example. Unfortunately the ContractAbbreviator attribute is not available by default. You have to add “%programfiles%\Microsoft\Contracts\Languages\CSharp\ContractExtensions.cs” to your project to make the attribute available.
[ContractAbbreviator] private void ValidateNameAndAge(string name, int age) { Contract.Requires(name != null); Contract.Requires(age >= 0); } public void Initialize(string name, int age) { ValidateNameAndAge(name, age); Contract.Ensures(Name == name); Contract.Ensures(Age == age); //init properties _name = name; _age = age; }
Summary
Contract abbreviators will allow you to specify reusable contracts. This will allow you to implement according to the “don’t repeat yourself” best practice.