Argument Validation

Some days ago Fredrik Normén wrote a post about how to validate a method's arguments. The validation methods or even using extension methods is not the problem, but offering a useful error message, when the argument is not valid and an exception is thrown. For such an exception we need the name of the argument. He brings up a bunch of ideas, but at the end he concentrates on two approaches. One takes the argument name as an argument to the validation method, the other one uses reflection to get the argument's name.

Each of these two approaches has a drawback. With the first one, you have to declare the name of the argument in each validation method, what's really painful. The second one is easier to use but reflection is not the best solution regarding performance. While I do not think, that this would really hurt most of the application that use such validation and as a commenter noted, the methods could be written in a way reflection only is used in case of validation failure, I made some thoughts about this validation thing.

I started with the first approach, where I think it's mainly a problem, if you want to chain some validation methods (using extension methods for validation). This would lead to some unesthetic statements like so:

argumentToValidate.IsRequired("argumentToValidate").IsShorterThan(20, "argumentToValidate").IsUpperCase("argumentToValidate"); 

So, if we could shorten this to something like in the code below, I think it would be acceptable.

argumentToValidate.IsRequired("argumentToValidate").IsShorterThan(20).IsUpperCase(); 

And what's really nice, is the fluent validation by using extension methods.  

My approach to a fluent validation

So how to accomplish that? I thought about the following:

// a generic object that holds the argument's value and the argument's name
public class Validator<T>
{
	public T Argument { get; set; }
	public string ArgumentName { get; set; }
	public Validator(T argument, string argumentName)
	{
		this.Argument = argument;
		this.ArgumentName = argumentName;
	}
}

// extension method which returns a Validator object
public static Validator<T> Validate<T>(this T argument, string argumentName)
{
	if (argument == null) 
		throw new ArgumentNullException(argumentName);
	return new Validator<T>(argument, argumentName);
} 

// some validation methods (also extension methods to make the validation fluent). 
public static Validator<int> GreaterThan(this Validator<int> v, int value)
{
	if (v.Argument <= value)
		throw new ArgumentException(String.Format("{0} must be greater than {1}", v.ArgumentName, value), v.ArgumentName);
	return v;
}

public static Validator<int> InRange(this Validator<int> v, int min, int max)
{
	if (v.Argument < min || v.Argument > max)
		throw new ArgumentException(String.Format("{0} must be between {1} and {2}", v.ArgumentName, min, max), v.ArgumentName);
	return v;
} 

Using this approach we can write validation as follows:

int primeNumber = 43;
primeNumber.Validate("primeNumber").GreaterThan(40).Odd().PrimeNumber(); 

While the Validate() method is the same for all types of objects it returns a type specific Validator<T> which has the effect that only appropriate validation extension methods are shown by intellisense.

Conclusion

I'm not sure, if this brings really some advantage. In some cases where you only need one validation method it may adds some code. But I think, it's a clean approach to validating arguments. What do you think about this?

Edit:

Should have read all comments. Roger Alsing came up with almost the same solution. One addition he makes, is the [DebuggerHidden] attribute on the validation methods, which has the effect, that it will break on the method which performs the Validate call, and not in the validation method.


Posted by: Dave
Posted on: 5/12/2008 at 10:07 PM
Tags: , Categories: Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (7) | Post RSSRSS comment feed
Administration: