【问题标题】: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);
}
【解决方案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;
}
}
您无法在异常中获取变量名。但是通过堆栈跟踪和您的源代码,应该可以轻松追踪。