有没有更好的方法来要求方法中的参数不为空?我不断检查我的方法需要的任何参数是否为空,如下所示。但我想知道是否有更好的方法。
public void MyMethod(string a, int b)
{
if(a==null){throw new ArgumentNullException("a");}
if(b==null){throw new ArgumentNullException("b");}
//more stuff here
}
您可以编写一些实用方法。这是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;
}
}
您无法在异常中获取变量名称。但是通过堆栈跟踪和您的源代码,应该可以轻松追踪。
没有其他更好的方法。这是大量 Microsoft 库处理这种情况的方式。
您始终可以使用扩展方法使其更清晰。
static IsNullArgument(this Object o, string arg)
{
if (o == null)
throw ArgumentNullException(arg);
}
我个人喜欢CutEdge.Conditions。它易于使用,并使其更具可读性。
Rick Brewster(Paint.NET 的作者)写了一篇关于 Fluent API 替代方案的博客:
http://blog.getpaint.net/2008/12/06/a-fluent-approach-to-c-parameter-validation/
这是我认为 C# 从 C++ 倒退的少数几个领域之一。
在 C++ 中,您可以编写
void foo(Bar& bar) { /*...*/ }
非常清楚地向编译器和其他foo
采用Bar
. 是的,有可能——通过努力——传递foo
一个空引用,但这不是真正合法的 C++。
您在 C# 中唯一的“解决方案”(各种)是让您的class
esstruct
代替,因为 .NET 中的值类型不能null
(在您的示例中,b永远不可能null
,因为它是 a 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);
}
null
对于 C# 来说,让引用变得(非常)更加困难,这当然会很好。例如,F# 没有可为空的类型。
有关此问题的一些有趣评论,请阅读空参考:十亿美元的错误(和评论)。
编辑:Eric Lippert在 2013 年 2 月的脚注中说“......碰巧当 C# 首次实现时,它具有始终可以为空的引用类型,......似乎Nullable<T>
可以实现任何类型的工作,并且引用类型默认是不可为空的。我们可以有一个类型系统,这Nullable<string>
是唯一合法的方式来表示“可以是null
”的字符串。...“