C# C语言中的空参数检查#
在C#中,在null不是有效值的每个函数中添加参数null检查有什么好的理由(除了更好的错误消息)吗?显然,使用s的代码无论如何都会抛出异常。这样的检查使得代码更慢,更难维护C# C语言中的空参数检查#,c#,function,null,C#,Function,Null,在C#中,在null不是有效值的每个函数中添加参数null检查有什么好的理由(除了更好的错误消息)吗?显然,使用s的代码无论如何都会抛出异常。这样的检查使得代码更慢,更难维护 void f(SomeType s) { if (s == null) { throw new ArgumentNullException("s cannot be null."); } // Use s } 主要的好处是,您从一开始就明确了方法的需求。这使其他开发人员可以清楚地看到,调用程序向
void f(SomeType s)
{
if (s == null)
{
throw new ArgumentNullException("s cannot be null.");
}
// Use s
}
主要的好处是,您从一开始就明确了方法的需求。这使其他开发人员可以清楚地看到,调用程序向方法发送空值确实是一个错误
该检查还将在执行任何其他代码之前停止该方法的执行。这意味着您不必担心该方法所做的修改未完成。是的,有很好的理由:
- 它准确地标识空值,这可能在
NullReferenceException
- 它使代码在无效输入时失败,即使某些其他条件意味着该值未被取消引用
- 它使异常在方法可能产生任何其他副作用之前发生,您可能会在第一次取消引用之前达到这些副作用
- 这意味着您可以确信,如果您将参数传递到其他内容中,您不会违反他们的约定
- 它记录了您的方法的需求(当然,使用它更好)
- 速度较慢:您是否发现这实际上是代码中的瓶颈,或者您是在猜测?空值检查非常快速,在绝大多数情况下,它们不会成为瓶颈
- 这使得代码更难维护:我认为恰恰相反。我认为使用代码更容易,因为代码清楚地表明了参数是否可以为null,并且您确信该条件是强制执行的
void f(SomeType s)
{
// Use s
Console.WriteLine("I've got a message of {0}", s);
}
它使用s
,但不会引发异常。如果s
为null是无效的,并且表示出现了问题,那么异常是这里最合适的行为
现在,把这些参数验证检查放在哪里是另一回事了。您可能决定信任自己类中的所有代码,因此不必担心私有方法。您可能决定信任程序集的其余部分,因此不必担心内部方法。几乎可以肯定,您应该验证公共方法的参数
旁注:ArgumentNullException
的单参数构造函数重载应该只是参数名,因此您的测试应该是:
if (s == null)
{
throw new ArgumentNullException("s");
}
或者,您可以创建一个扩展方法,允许使用更简洁的:
s.ThrowIfNull("s");
在我的(泛型)扩展方法版本中,我让它在非null时返回原始值,允许您编写如下内容:
this.name = name.ThrowIfNull("name");
如果你不太在意的话,你也可以有一个不带参数名的重载。如果没有一个明确的
if
检查,如果你不拥有代码,就很难找出什么是null
如果您在没有源代码的库中得到NullReferenceException
,那么您很可能很难弄清楚自己做错了什么
这些if
检查不会使代码明显变慢
请注意,的参数是参数名,而不是消息。
你的代码应该是
如果(s==null)抛出新的ArgumentNullException(“s”);
我编写了一个代码片段以简化此过程:
检查空参数
tna
抛出新ArgumentNullException的代码段
渣
膨胀
周边地区
参数
检查空值的参数
价值
当您遇到异常时,它会保存一些调试
ArgumentNullException明确声明为空的是“s”
如果您没有进行该检查并让代码崩溃,那么您将从该方法中的某个未标识行获得一个NullReferenceException。在发布版本中,你不会得到行号 我同意乔恩的观点,但我想补充一点 我对何时添加显式空检查的态度基于以下前提:
- 单元测试应该有一种方法来练习程序中的每一条语句
语句是语句李>throw
的结果是一条语句if
- 因此,如果(x==null)抛出任何东西,应该有一种方法来练习
中的
代码>抛出
Debug.Assert(x!=null)代码>
如果有可能执行该语句,则编写该语句,然后编写执行该语句的单元测试
尤其重要的是,公共类型的公共方法以这种方式检查它们的参数;你不知道你的用户会做什么疯狂的事情。尽快给他们“嘿,你这个笨蛋,你做错了!”例外
相比之下,私有类型的私有方法更可能处于控制参数的情况下,并且可以有力地保证参数永远不为null;使用断言来记录该不变量。如果需要更好的方法来确保不获取任何空对象作为参数,您可能需要看看 原始代码:
void f(SomeType s)
{
if (s == null)
{
throw new ArgumentNullException("s cannot be null.");
}
// Use s
}
将其改写为:
void f(SomeType s)
{
if (s == null) throw new ArgumentNullException(nameof(s));
}
使用int i = Age ?? 0;
if (age == null || age == 0)
if (age.GetValueOrDefault(0) == 0)
if ((age ?? 0) == 0)
int i = age.HasValue ? age.Value : 0;