验证参数
编写方法时,应在执行任何操作之前首先验证参数。例如,假设我们有一个代表人的类:
public class Person
{
public readonly string Name;
public readonly int Age;
public class Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
这个Person类出了什么问题?在将值设置为Person字段之前,不验证名称和年龄。 “验证?”是什么意思?应该检查两个参数,它们的值是可接受的。例如,如果name的值是空字符串怎么办?或者年龄的值是-10?
通过在值不可接受时抛出ArgumentExceptions或派生异常来执行验证参数。例如:
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;
}
这可以正确验证Person的构造函数接收的参数。
Tedium ad Nauseum
因为你已经在很长一段时间内验证了参数(对吗?),你可能已经厌倦了写这些if(....)在你的所有方法中抛出Argument ...语句。
答案 0 :(得分:6)
您可以查看Code Contracts in .NET 4.0。
如果您不想等待代码合同,您可能还需要查看FluentValidation Library on CodePlex。
最终,您仍然需要将控制参数值的规则放在某处 - 这只是决定您是否更喜欢命令式样式(例如string.IsNullOrEmpty)或声明性样式。
验证输入是编写可靠代码的关键实践 - 但它肯定是重复和冗长的。
答案 1 :(得分:2)
使用更复杂的类型而不是原语可能会对你有所帮助。
例如,如果您花时间定义类似PersonName
类的内容,则可以在其中验证 ,而不必在其他所有内容上进行验证需要在其上有名称的对象。
显然,如果您有多个使用相同字段类型的对象,这只会有助于解决问题。
答案 2 :(得分:1)
您可以尝试使用Castle Validation Framework =&gt; http://www.castleproject.org/activerecord/documentation/v1rc1/usersguide/validation.html
OR
您可以使用我创建的简单验证框架。两个框架都使用基于属性的验证。请查看以下链接:
http://www.highoncoding.com/Articles/424_Creating_a_Domain_Object_Validation_Framework.aspx
答案 3 :(得分:1)
有基于Postsharp的选项。 code-o-matic就是其中之一。它允许你编写这样的代码:
public class Person(
[NotNull, NotEmpty] string name,
[NotNull, NotEmpty] int age
)
{
this.Name = name;
this.Age = age;
}
我每天都在工作中使用它。
答案 4 :(得分:-1)
我将用D编程语言提供解决方案。我不知道C#泛型和可变参数是多么强大,因为我不使用C#,但也许你可以适应这个:
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.
}
}
}
用法:
class Foo {
SomeType myMethod(T arg1, U arg2, V arg3) {
validate(arg1, arg2, arg3);
// Do non-boilerplate validation.
// Method body.
}
}