【问题标题】:How to avoid argument validation如何避免参数验证
【发布时间】:2009-10-22 17:24:30
【问题描述】:

验证原始参数和“复杂数据”

验证参数

在编写方法时,应先验证参数,然后再执行任何操作。例如,假设我们有一个代表人的类:

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 类有什么问题? name 和 age 在它们的值被设置为 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 的构造函数接收的参数。

乏味和恶心

因为您已经验证参数很长时间了(对吗?),您可能已经厌倦了在所有方法中编写这些 if (....) throw Argument... 语句。

我们可以做些什么来避免在您的代码中多次写入 String.IsNullOrEmpty?

【问题讨论】:

  • 您有什么理由不想使用属性(而不是公共字段)并将验证放在其中?

标签: c# argument-validation


【解决方案1】:

您可以查看Code Contracts in .NET 4.0

如果您不想等待代码合同,您可能还想查看FluentValidation Library on CodePlex

最终,您仍然需要将管理参数值的规则放在某处 - 只需决定您更喜欢命令式风格(例如 string.IsNullOrEmpty)还是声明式风格。

验证您的输入是编写可靠代码的关键实践 - 但它肯定是重复和冗长的。

【讨论】:

  • 我应该看什么代码合同?
  • CC 提供了一种简洁的语法来表达方法的约束和前提条件。它还定义了一个标准模型,用于使用异常报告违反这些约束的情况。虽然它并没有消除考虑和定义先决条件的需要,但它有助于在代码中以一致的方式表达它们。此外,如果您使用 VSTS,许多约束可以静态验证(在编译时)帮助您在编写代码时检测问题,而不是运行它。
【解决方案2】:

使用更复杂的类型而不是原始类型可能会有所帮助。

例如,如果您花时间定义类似PersonName 类的东西,您可以在那里进行验证,而您不必在所有其他对象上都验证它需要有一个名字。

显然,如果您有多个使用相同字段类型的对象,这只会帮助解决问题。

【讨论】:

    【解决方案3】:

    您可以尝试使用 Castle Validation Framework => http://www.castleproject.org/activerecord/documentation/v1rc1/usersguide/validation.html

    您可以使用我创建的简单验证框架。这两个框架都使用基于属性的验证。看看下面的链接:

    http://www.highoncoding.com/Articles/424_Creating_a_Domain_Object_Validation_Framework.aspx

    【讨论】:

      【解决方案4】:

      有基于Postsharp 的选项。 code-o-matic 就是其中之一。它可以让你编写这样的代码:

      public class Person(
          [NotNull, NotEmpty] string name,
          [NotNull, NotEmpty] int age
      )
      {
          this.Name = name;
          this.Age = age;
      }
      

      我每天在工作中都使用它。

      【讨论】:

      • 上帝,我希望这是正确的语言。如果我必须再次验证一个简单条件(如 null)的参数,我会开枪!
      【解决方案5】:

      我将用 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.
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-01-22
        • 2021-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-08
        相关资源
        最近更新 更多