繁体   English   中英

一组用于检查嵌套静态类中的参数的方法

[英]A set of methods for checking arguments in nested static class

我有一个静态类ArgumentHelper ,它可以检查例如: ArgumentHelper.NotNull(instance, "instance") 但它适用于一些标准的内置.net框架类,如果我实现自己的类,我不能把检查放在ArgumentHelper中,因为这个类太大了。 所以我在想,我找到了一个解决方案:我将在每个新制作的自定义类中创建一个嵌套的静态类:

public class MyClass
{
    private int x;

    public MyClass (int x)
    {   
        if (x < 0) throw new ArgumentOutOfRangeException (...);

        this.x = x;
    }

    public static class Arg
    {
       public static void NotZero (MyClass mc)
       {
           if (mc.x == 0) throw ....
       }
    }
}

所以现在:

public void myMethod (MyClass mc)
{
    MyClass.Arg.NotZero (mc); // will throw excweption if x == 0

    do some stuff
}

这是一个好主意,还是你有不同的方法?

有很多方法可以做到这一点,但我会说这种方式不必要地复杂化。 您可以创建一个具有检查不同参数的逻辑的静态类,而不是在整个地方创建类。 例如:

 //Common methods for validating method parameters
 public static class Ensure
 {
      public static void NotNull(object o, string paramName)
      {
          if (null == o)
              throw new ArgumentNullException(paramName);
      }

      public static void NotZero(Point p, string paramName){ /*logic*/ }

      public static void GreaterThanZero(int i, string paramName)
      {
          if (i <= 0)
               throw new ArgumentException("Must be greater than zero", paramName);

      }
 }

然后在你的班上:

 public class MyCustomClass
 {
      public void SomeMethod(object o, int i, Point p)
      {
            //Guards
            Ensure.NotNull(o, "o");
            Ensure.GreaterThanZero(i, "i");
            Ensure.NotZero(p, "p");
      }
 }

此外,Microsoft Research还有一个名为“Code Contracts”的类似项目。 您可以在此处阅读更多相关信息: http//visualstudiomagazine.com/articles/2010/06/23/code-contracts.aspx

更新

为了减少行数,你可以这样做:

public static class Ensure
{
    public static void NotNull(params object[] objects)
    {
       if (objects.Any(x => null == x)
          throw new ArgumentNullException();
    }
}

然后在你的方法:

public void example(object o, int i, Point p)
{
    Ensure.NotNull(o, i, p);
}

我更喜欢使用更好的命名和传递接口。

例如,你可以拥有这个类:

public static class ThrowOn
{
    public static T Null<T>(T val, string name) where T : object
    {
        if (val == null) throw new ArgumentNullException(name);
        return val;
    }
}

并以这种方式使用它:

private MyObject _mine;

public SomeConstructor(MyObject mine)
{
    _mine = ThrowOn.Null(mine, "mine");
}

这使得非常清楚会抛出异常。 我使用泛型来确保它的类型很强,你不能将测试结果分配给错误的类型。

我喜欢这个,因为它可以保持你的构造函数的美观和整洁,使代码有所不同,它完全符合它在框中所说的内容。

如果您喜欢读取的方式,也可以将类命名为ThrowIf

这也可以在扩展方法中完成:

public static class Extensions
{
    public static T ThrowOnNull<T>(this T val, string name) where T : object
    {
        if (val == null) throw new ArgumentNullException(name);
        return val;
    }
}

在使用中看起来像这样:

private MyObject _mine;

public SomeConstructor(MyObject mine)
{
    _mine = mine.ThrowOnNull("mine");
}

我听过这种方法的一个论点是堆栈框架的顶部不是异常的来源,但我对客户读取堆栈爬行的能力更有信心。

这与我的其他答案截然不同,所以我正在创建一个新答案。 另一种选择是通过像PostSharp这样的框架使用AOP 这种方法的警告是AOP通常需要修改编译器以添加自定义编译步骤或与依赖注入相结合才能工作。 通常这很好,但根据您的环境,它可以被视为一种限制。

PostSharp有一个关于这个问题的教程,让你用一些强制执行“契约”的属性来装饰你的方法参数:

public void Foo( [NotNull] string bar ) {}

PostSharp会将其重写为(编译后时间)

public void Foo(string bar ) 
{
    if (null == bar)
       throw new ArgumentNullExpcetion(bar, "bar");
}

您可以阅读更多有关其工作原理以及此处支持的内容: 使用PostSharp 3验证参数,字段和属性

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM