Click here to Skip to main content
Click here to Skip to main content

CuttingEdge.Conditions

, 23 Jun 2011 MIT
Rate this:
Please Sign up or sign in to vote.
A pre- and postcondition validation framework based on .NET 3.5 extension methods

Introduction

CuttingEdge.Conditions is a library that helps developers to write pre- and postcondition validations in their C# 3.0 and VB.NET 9 code base. Writing these validations is easy and it improves the readability and maintainability of code.

Dependency

CuttingEdge.Conditions is language independent and can be used with both C# 3.0 and VB9. The library can be run on machines that do not have .NET 3.5 installed. While the CuttingEdge.Conditions.dll assembly itself has a dependency on System.Core (.NET 3.5), users can safely add it to their .NET 2.0 projects (as long as the C# 3.0 or VB9 compilers are used).

Conditions

Writing precondition validations raises the quality of code. Code with validations is easier to understand and allows developers to find bugs faster, mostly during development instead of during debugging. Writing precondition validations however has always been the poor relation in programming. It takes time to write it and many developers I worked with (even the ones I respect) skipped writing them.

Skipping precondition validations will lead to code that is more difficult to use and is likely to be misused. It allows developers to pass invalid method arguments, which results in unexpected program behavior and those awful NullReferenceExceptions from deep down the call stack. It leads to a higher amount of bugs and thus more time spent debugging.

The CuttingEdge.Conditions library is an attempt to lower the barrier of writing precondition validations and make code more readable, thus resulting in better code, less bugs, and shorter development cycles.

To understand how CuttingEdge.Conditions tries to achieve this, let us first have a look at some code we might write on a daily basis. Here is an C# example of precondition validations, the old fashioned way:

void TheOldFashionWay(int id, IEnumerable<int> collection, DayOfWeek day)
{
    if (id < 1)
    {
        throw new ArgumentOutOfRangeException("id", String.Format(
            "id should be greater than 0. The actual value is {0}.", id));
    }
    if (collection == null)
    {
        throw new ArgumentNullException("collection", 
            "collection should not be empty");
    }
    if (collection.Count() == 0)
    {
        throw new ArgumentException("collection should not be empty", 
            "collection");
    }
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Friday)
    {
        throw new InvalidEnumArgumentException(String.Format(
            "day should be between Monday and Friday. " +
            "The actual value is {0}.", day));
    }

    // Do method work
}

That’s an awful amount of code for a few simple validations! Here’s how it looks if CuttingEdge.Conditions would be adopted:

void TheConditionsWay(int id, IEnumerable<int> collection, DayOfWeek day)
{
    Condition.Requires(id, "id").IsGreaterThan(0);
    Condition.Requires(collection, "collection").IsNotEmpty();
    Condition.Requires(day, "day").IsInRange(DayOfWeek.Monday, DayOfWeek.Friday);

    // Do method work
} 

That’s quite different, isn't it? It’s not only far less code; it’s also very readable. And please note that both methods have exactly the same contract. Both methods throw exactly the same exceptions and exception messages!

Besides these normal precondition checks, CuttingEdge.Conditions enables you to do postcondition checks as well. Unlike a precondition, the violation of a postcondition has purely an internal cause. It can be considered a bug. Throwing an ArgumentException in that case would clearly confuse the developer using that code. Because of this difference, CuttingEdge.Conditions will always throw a PostconditionException on a violation of a postcondition.

Here is an example of a postcondition check:

public ICollection PostconditionExample()
{
    object obj = Activator.CreateInstance(typeof(Collection<int>));

    Condition.Ensures(obj, "obj").IsNotNull().IsOfType(typeof(ICollection));

    return (ICollection)obj;
} 

The postcondition example shows two interesting things. Firstly, The Ensures extension method is used to start a postcondition validation. Secondly, method calls can be chained in a fluent manner as shown with the IsNotNull and IsOfType methods.

The API

The CuttingEdge.Conditions API has many validation methods that easily cover 99% of your validation needs. There are currently 412 extension methods for 53 different checks. The API can be divided in eight groups: 

  • Entry point methods
  • Null check methods
  • Type check methods
  • Comparison checks
  • Collection checks
  • String checks
  • Numeric checks
  • Evaluations

The number of methods will possibly grow over time, and please comment here, on my blog or on CodePlex if you think there are validations missing. I will consider adding them to the library. Also note that it’s easy for you to extend the API with your own methods, by simply placing extension methods in your own project. For more information on extending CuttingEdge.Conditions, please read the Extending CuttingEdge.Conditions wiki on CodePlex.

More Information

This third stable release of the CuttingEdge.Conditions library has just been released. You can download the source and runtime library from CodePlex. Please visit conditions.codeplex.com or my blog.

Happy validating!

License

This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

The .NET Junkie
Software Developer (Senior)
Netherlands Netherlands
I'm a freelance developer from the Netherlands, working with .NET technology on a daily basis, and officially diagnosed as a workaholic.
Follow on   Twitter

Comments and Discussions

 
GeneralNice but .. PinmemberGuido_d16-Feb-10 6:44 
GeneralRe: Nice but .. PinmemberVCSKicks16-Feb-10 6:51 
GeneralRe: Nice but .. PinmemberThe .NET Junkie16-Feb-10 7:43 
GeneralRe: Nice but .. PinmemberPaul Selormey23-Jun-11 16:03 
GeneralNice! PinmemberJason Law9-Sep-09 15:38 
QuestionEnsuresWhileDebugging PinmemberAlexey Romanov7-Aug-08 1:04 
AnswerRe: EnsuresWhileDebugging [modified] PinmemberThe .NET Junkie6-Sep-08 7:32 
GeneralRe: EnsuresWhileDebugging PinmemberMember 145294324-Jun-11 2:33 
GeneralRe: EnsuresWhileDebugging PinmemberThe .NET Junkie24-Jun-11 4:53 
GeneralWhy not design by contract Pinmemberdanidanidani31-Jul-08 4:15 
AnswerRe: Why not design by contract [modified] PinmemberThe .NET Junkie31-Jul-08 4:44 
GeneralRe: Why not design by contract Pinmemberdanidanidani31-Jul-08 4:52 
QuestionLinFu? PinmemberJudah Himango21-Jul-08 10:22 
AnswerRe: LinFu? [modified] PinmemberThe .NET Junkie23-Jul-08 1:53 
Generalmaybe idea PinmemberMr.PoorEnglish17-Jul-08 22:48 
GeneralOne more question PinmemberMr.PoorEnglish17-Jul-08 23:40 
GeneralRe: One more question PinmemberThe .NET Junkie20-Jul-08 11:04 
GeneralRe: One more question PinmemberMr.PoorEnglish20-Jul-08 12:35 
GeneralRe: One more question PinmemberThe .NET Junkie20-Jul-08 13:29 
GeneralRe: One more question PinmemberMr.PoorEnglish21-Jul-08 0:58 
GeneralRe: One more question PinmemberThe .NET Junkie21-Jul-08 5:38 
GeneralExtension methods on .net2.0 Pinmembergeo_m17-Jul-08 1:53 
AnswerRe: Extension methods on .net2.0 PinmemberThe .NET Junkie18-Jul-08 9:07 
GeneralRe: Extension methods on .net2.0 Pinmembergeo_m21-Jul-08 1:27 
GeneralRe: Extension methods on .net2.0 PinmemberQwertie6-Aug-08 12:04 
GeneralRe: Extension methods on .net2.0 PinmemberThe .NET Junkie13-Aug-09 3:33 
GeneralGood. Here's an idea for improvement. PinmemberJudah Himango16-Jul-08 18:01 
GeneralRe: Good. Here's an idea for improvement. PinmemberThe .NET Junkie17-Jul-08 3:07 
GeneralRe: Good. Here's an idea for improvement. PinmemberJudah Himango17-Jul-08 7:13 
Hi again.
 
Thanks for the info.
 
How about a syntax like Requires(() => id).IsGreaterThan(0)?
 
Thanks for the article and code, will be giving it a spin this week. By the way, are you aware there are some internal design-by-contract attributes in .NET 3.5? Check out the Microsoft.Contracts.Contract class inside System.Core.dll. Some interesting stuff in there that might influence your designs.
 


Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Upon this disciple I'll build my new religion?
The apostle Paul, modernly speaking: Epistles of Paul
 
Judah Himango


GeneralRe: Good. Here's an idea for improvement. PinmemberThe .NET Junkie17-Jul-08 8:51 
GeneralRe: Good. Here's an idea for improvement. PinmemberJudah Himango17-Jul-08 11:35 
GeneralRe: Good. Here's an idea for improvement. [modified] PinmemberThe .NET Junkie18-Jul-08 13:29 
GeneralRe: Good. Here's an idea for improvement. PinmemberJudah Himango20-Jul-08 10:49 
GeneralRe: Good. Here's an idea for improvement. PinmemberThe .NET Junkie20-Jul-08 11:53 
GeneralRe: Good. Here's an idea for improvement. PinmemberJudah Himango20-Jul-08 11:57 
GeneralRe: Good. Here's an idea for improvement. PinmemberThe .NET Junkie4-Aug-08 4:09 
GeneralRe: Good. Here's an idea for improvement. PinmemberJudah Himango29-Oct-08 12:43 
GeneralRe: Good. Here's an idea for improvement. PinmemberThe .NET Junkie8-Nov-08 4:41 
GeneralRe: Good. Here's an idea for improvement. Pinmemberbalazs_hideghety9-Feb-09 11:30 
AnswerRe: Good. Here's an idea for improvement. PinmemberPatrick Wolf19-May-09 18:37 
GeneralRe: Good. Here's an idea for improvement. PinmemberThe .NET Junkie19-May-09 22:54 
AnswerRe: Good. Here's an idea for improvement. PinmemberPatrick Wolf25-May-09 6:16 
GeneralRe: Good. Here's an idea for improvement. PinmemberThe .NET Junkie25-May-09 9:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 23 Jun 2011
Article Copyright 2008 by The .NET Junkie
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid