In this post of the series on Code Contracts, it’s all about the Contract.EndContractBlock method. This method could be seen as some magical marker to get the benefits of Code Contracts and all the checks that come with them. It is intended to be used in legacy code to mark the end of a contract block.
Given the example I used in my previous posts:
public string RepeatFirstCharacter(string input, int count)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (input.Length < 1)
{
throw new ArgumentException("The input should have at least one character.", "input");
}
if (count <= 0)
{
throw new ArgumentOutOfRangeException("count");
}
return new string(input.ToCharArray(0, 1)[0], count);
}
This could very easy be rewritten with a call to the Contract.EndContractBlock() method to get the benefit of the Code Contracts. It would end up like this:
public string RepeatFirstCharacter(string input, int count)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (input.Length < 1)
{
throw new ArgumentException("The input should have at least one character.", "input");
}
if (count <= 0)
{
throw new ArgumentOutOfRangeException("count");
}
Contract.EndContractBlock();
return new string(input.ToCharArray(0, 1)[0], count);
}
There are some things to note here though. Not every block of argument checking etc. could be easily marked with the EndContractBlock call. Any code that precedes the call to Contract.EndContractBlock() must adhere to the following form:
if throw
There can not be an else branch in the statements. Also the code in the condition must be side-effect free, and the exception that is to be thrown must be at least as visible as the method in which the contract occurs. As mentioned already in my post on Contract.Requires, the conditions in the IF-THEN-THROW statements are the negation of the conditions that occur as part of the Contract.Requires method. This is something to be aware of when working with contracts.
The Code Contracts binary rewriter will convert the code marked by the Contract.EndContractBlock into code similar to the code that uses Contract.Requires which was explained in my previous post here. The Contract.EndContractBlock call is only needed as a marker when there are no other or further calls to the Contract’s static members. If we were to enhance the code with an additional precondition, or with a new post condition, it would make the call to Contract.EndContractBlock() obsolete.
The following example would also result in use of all benefits of Code Contracts, even though there is no explicit call to Contract.EndContractBlock():
public string RepeatFirstCharacter(string input, int count)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (input.Length < 1)
{
throw new ArgumentException("The input should have at least one character.", "input");
}
if (count <= 0)
{
throw new ArgumentOutOfRangeException("count");
}
Contract.Ensures(Contract.Result<string>().Length == count);
return new string(input.ToCharArray(0, 1)[0], count);
}
This example has a new post condition that has been added. The call to Contract.Ensures is a post conditional check, which is performed on the result of the method. Contract.Ensures is to be explained in the next post in this series.
That’s it for now.
Meile