Code Contracts: validating arrays and collections
Validating collections before using them is very common task when we use built-in generic types for our collections. In this posting I will show you how to validate collections using code contracts. It is cool how much awful looking code you can avoid using code contracts.
- Controlling randomizer using code contracts
- Using runtime checking of code contracts in Visual Studio 2010
- Code Contracts: Hiding ContractException
- Code Contracts: Unit testing contracted code
- Forcing code contracts through interface contracts
- Invariant code contracts – using class-wide contracts
- Code contracts and inheritance
- Enabling XML-documentation for code contracts
- Using Sandcastle to build code contracts documentation
- Code Contracts: How they look after compiling?
- Code Contracts: validating arrays and collections
Failing code
Let’s suppose we have method that calculates sum of all invoices in collection. We have class Invoice and one of properties it has is Sum. I don’t introduce here any complex calculations on invoices because we have another problem to solve in this topic. Here is our code.
public static decimal CalculateTotal(IList<Invoice> invoices)
{
var sum = invoices.Sum(p => p.Sum);
return sum;
}
This method is very simple but it fails when invoices list contains at least one null. Of course, we can test if invoice is null but having nulls in lists like this is not good idea – it opens green way for different coding bugs in system. Our goal is to react to bugs ASAP at the nearest place they occur.
There is one more way how to make our method fail. It happens when invoices is null. I thing it is also one common bugs during development and it even happens in production environments under some conditions that are usually hardly met.
Now let’s protect our little calculation method with code contracts. We need two contracts:
- invoices cannot be null
- invoices cannot contain any nulls
Our first contract is easy but how to write the second one?
Solution: Contract.ForAll
Preconditions in code are checked using Contract.Ensures method. This method takes boolean value as argument that sais if contract holds or not. There is also method Contract.ForAll that takes collection and predicate that must hold for that collection. Nice thing is ForAll returns boolean. So, we have very simple solution.
public static decimal CalculateTotal(IList<Invoice> invoices)
{
Contract.Requires(invoices != null);
Contract.Requires(Contract.ForAll<Invoice>(invoices, p => p != null));
var sum = invoices.Sum(p => p.Sum);
return sum;
}
And here are some lines of code you can use to test the contracts quickly.
var invoices = new List<Invoice>();
invoices.Add(new Invoice());
invoices.Add(null);
invoices.Add(new Invoice());
//CalculateTotal(null);
CalculateTotal(invoices);
If your code is covered with unit tests then I suggest you to write tests to check that these contracts hold for every code run.
Conclusion
Although it seemed at first place that checking all elements in collection may end up with for-loops that does not look so nice we were able to solve our problem nicely. ForAll method of contract class offered us simple mechanism to check collections and it does it smoothly the code-contracts-way.