Reputation: 4793
Validating Arguments
When writing a method, arguments should be validated first before any operations are performed. For example, let's say we've got a class representing people:
public class Person
{
public readonly string Name;
public readonly int Age;
public class Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
What's wrong with this Person class? name and age aren't validated before their values are set as fields of Person. What do I mean by "validated?" Both argument should be checked that their values are acceptable. For example, what if name's value is an empty string? Or age's value is -10?
Validating the arguments is performed by throwing ArgumentExceptions or derived exceptions when the values are unacceptable. For example:
public class Person(string name, int age)
{
if (String.IsNullOrEmpty(name))
{
throw new ArgumentNullException
("name", "Cannot be null or empty.");
}
if (age <= 0 || age > 120)
{
throw new ArgumentOutOfRangeException
("age", "Must be greater than 0 and less than 120.");
}
this.Name = name;
this.Age = age;
}
This properly validates the arguments Person's constructor receives.
Tedium ad Nauseum
Because you've been validating arguments for a long time (right?), you're probably tired of writing these if (....) throw Argument... statements in all of your methods.
Upvotes: 5
Views: 526
Reputation: 12469
There are options based on Postsharp. code-o-matic is one of them. It lets you write code like this:
public class Person(
[NotNull, NotEmpty] string name,
[NotNull, NotEmpty] int age
)
{
this.Name = name;
this.Age = age;
}
I use this every day at work.
Upvotes: 1
Reputation: 20066
You can try using the Castle Validation Framework => http://www.castleproject.org/activerecord/documentation/v1rc1/usersguide/validation.html
OR
You can use a simple validation framework that I created. Both the frameworks uses Attribute based validation. Check out the link below:
http://www.highoncoding.com/Articles/424_Creating_a_Domain_Object_Validation_Framework.aspx
Upvotes: 1
Reputation: 111027
You may be helped by using more complex types rather than primitives.
For example, if you take the time to define something like a PersonName
class, you can have the validation there, and you don't have to keep validating it on every other object that needs to have a name on it.
Obviously this is only going to help the problem if you have multiple objects that use the same field types.
Upvotes: 2
Reputation: 131676
You can look into Code Contracts in .NET 4.0.
You may also want to look at the FluentValidation Library on CodePlex if you don't want to wait for code contracts.
Ultimately, you still need to put the rules that govern argument values somewhere - it just a matter of deciding whether you prefer an imperative style (e.g. string.IsNullOrEmpty) or a declarative one.
Validating your inputs as is a key practice for writing solid code - but it certainly can be repetitive and verbose.
Upvotes: 6
Reputation: 68740
I'll give a solution in the D programming language. I don't know how powerful C# generics and variadics are because I don't use C#, but maybe you could adapt this:
void validate(T...)(T args) { // args is variadic.
foreach(arg; args) { // Iterate over variadic argument list.
static if(isSomeString!(typeof(arg))) { // Introspect to see arg's type.
if(arg.isNullOrEmpty) {
throw new ArgException(
"Problem exists between keyboard and chair.");
}
} else static if(isOtherTypeWithBoilerPlateValidation!(typeof(arg))) {
// Do more boilerplate validation.
}
}
}
Usage:
class Foo {
SomeType myMethod(T arg1, U arg2, V arg3) {
validate(arg1, arg2, arg3);
// Do non-boilerplate validation.
// Method body.
}
}
Upvotes: -2