Gunnar Peipman's ASP.NET blog

ASP.NET, C#, SharePoint, SQL Server and general software development topics.

Sponsors

News

 
 
 
DZone MVB

Links

Social

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.

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:

  1. invoices cannot be null
  2. 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.

P.S. I suggest you also read devlicio.us blog posting Validating Collections with Code Contracts by Derik Whittaker.

Comments

No Comments