【问题标题】:Is there a way to require that an argument provided to a method is not null?有没有办法要求提供给方法的参数不为空?
【发布时间】:2010-10-19 18:04:51
【问题描述】:

有没有更好的方法来要求方法中的参数不为空?我不断检查我的方法需要的任何参数是否为空,如下所示。但我想知道是否有更好的方法。

public void MyMethod(string a, int b)
{
   if(a==null){throw new ArgumentNullException("a");}
   if(b==null){throw new ArgumentNullException("b");}

   //more stuff here
}

【问题讨论】:

标签: c# null methods arguments


【解决方案1】:

没有其他更好的方法。这是大量 Microsoft 库处理这种情况的方式。

您总是可以使用扩展方法使其更清晰。

static IsNullArgument(this Object o, string arg)
{
    if (o == null)
        throw ArgumentNullException(arg);
}

【讨论】:

    【解决方案2】:

    我个人喜欢CuttingEdge.Conditions。它易于使用,并且更具可读性。

    【讨论】:

      【解决方案3】:

      Rick Brewster(Paint.NET 的作者)发表了一篇关于 Fluent API 替代方案的博客:

      http://blog.getpaint.net/2008/12/06/a-fluent-approach-to-c-parameter-validation/

      【讨论】:

        【解决方案4】:

        这是我认为 C# 从 C++ 倒退的少数几个领域之一。

        在 C++ 中,您可以编写

        void foo(Bar& bar) { /*...*/ }
        

        向编译器和其他人清楚地表明foo 采用了Bar 的实际实例。是的,有可能——通过努力——传递 foo 一个空引用,但这不是真正合法的 C++。

        您在 C# 中唯一的“解决方案”(某种)是让您的 classes structs 代替,因为 .NET 中的值类型不能是 null(在您的示例中,b 永远不可能是null,因为它是System.Int32)。对bar() 的调用将无法编译:

            class A { }
            struct B { }
        
            static void foo(A a) { }
            static void bar(B b) { }
        
            static void Main(string[] args)
            {
                foo(null);
                bar(null);
            }
        

        对于 C# 来说,如果让 null 引用变得(更)困难,这当然会很好;例如,F# 没有可为空的类型。

        有关此问题的一些有趣评论,请阅读Null References: The Billion Dollar Mistake(和 cmets)。


        编辑:Eric Lippert 的 2013 年 2 月脚注说:“...碰巧当 C# 首次实现时,它具有始终可以为空的引用类型,...这似乎是合理的Nullable<T> 可以在任何类型上实现,然后引用类型默认是不可为空的。我们可以有一个类型系统,其中 Nullable<string> 是表示“可以是 @987654337 的字符串的唯一合法方式@"...."

        【讨论】:

          【解决方案5】:

          您可以编写一些实用方法。这是java中的常见模式。

          用户代码:

          public void MyMethod(string a, int b)
          {
              //validate each
              Objects.RequireNotNull(a);
              Objects.RequireNotNull(b);
          
              //or validate in single line as array 
              Objects.RequireNotNullArray(a, b);
          }
          

          实现代码:

          public static class Objects
          {
              public static T RequireNotNull<T>(T arg)
              {
                  if(arg == null)
                  {
                      throw new ArgumentNullException();
                  }
                  return arg;
              }
          
              public static object[] RequireNotNullArray(params object[] args)
              {
                  return RequireNotNullArray<object>(args);
              }
          
              public static T[] RequireNotNullArray<T>(params T[] args)
              {
                  Objects.RequireNotNull(args);
                  for(int i=0; i<args.Length; i++)
                  {
                      T arg = args[i];
                      if(arg == null)
                      {
                          throw new ArgumentNullException($"null entry at position:{i}");
                      }
                  }
                  return args;
              }
          
          }
          

          您无法在异常中获取变量名。但是通过堆栈跟踪和您的源代码,应该可以轻松追踪。

          【讨论】:

            猜你喜欢
            • 2022-11-17
            • 1970-01-01
            • 1970-01-01
            • 2011-03-18
            • 1970-01-01
            • 2019-07-30
            • 2020-12-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多