2010-12-07 49 views
2

我有一个奇怪的问题,我一直在想,但永远不会看到实际用途。我期待看看是否有足够的理由。什么时候处理空指针/引用异常首选做空检查?

什么时候处理空指针/引用异常首选做空检查?如果有的话。

这适用于任何必须处理具有异常处理功能的空指针/引用的语言。

我对此的常见回应是在执行任何指针/引用之前执行空检查。如果非null,继续像正常一样使用它。如果为null,则处理该错误或将其提升。

即(在C#)

string str = null; 
if (str == null) 
{ 
    // error! 
} 
else 
{ 
    // do stuff 
    int length = str.Length; 
    // ... 
} 

但是,如果我们不这样做的检查,只是一味地使用它,一个异常将提高。

string str = null; 
int length = str.Length; // oops, NullReferenceException 
// ... 

是一个例外,我们当然可以抓住它所以没有从这样阻止我们(或有):

string str = null; 
try 
{ 
    int length = str.Length; // oops, NullReferenceException 
    // ... 
} 
catch (NullReferenceException ex) 
{ 
    // but that's ok, we can handle it now 
} 

现在我承认,这不是最干净代码,但它是不低于工作代码,我通常不会这样做。但是,有没有设计模式或者这样做有用?也许比直接做更有用,事先没有检查。

我能想象到的唯一情况可能是有用的是在一个多线程环境中,一个不受保护的共享变量被设置为null太早。但是这种情况多久发生一次?保护变量的好代码不会有这个问题。或者如果有人在编写调试器,并希望显式抛出异常,只是为了包装它或什么。也许一个看不见的性能好处或消除代码中其他事物的需要?

我可能已经回答了我的一些问题,但有没有其他用途来做到这一点?我并不是在寻找,“这样做只是因为我们可以”这样的例子,或者只是写得不好的代码,但是它的实际用途。虽然我会保持不变,“没有实际用处,请检查一下。”

+0

永远不会捕获一个`NullReferenceException`。这意味着你的代码有些错误。 – leppie 2010-12-07 08:30:22

+1

我不确定每个人都明白我的问题的意图,但是我会从中得出这样的结论,它从来没有真正有用,并且在使用它的地方没有模式。我知道我们不应该在有更好的方法来处理这件事情时这样做,我只是想知道是否有足够的理由去做。但是伊格纳西奥和豪伊的答案是一个足够强烈的理由,为什么它没有完成。 – 2010-12-09 01:51:58

+0

我完全不知道为什么这是-1。 upvoted,因为这是一个有趣的问题,但答案可能是语言和平台特定的。 – scriptocalypse 2011-04-27 23:27:17

回答

3

问题是所有空指针异常看起来都很相似。可以添加的任何会计信息指示哪个名称触发该异常不会比仅仅首先检查null更高效。

1

如果您希望该值不为空,那么执行任何检查都没有意义。但是,例如,在接受参数时,测试您需要为非空的参数并根据需要引发ArgumentNullExceptions是有意义的。

这是首选的原因有两个:

  1. 通常,您将使用ArgumentNullException构造的一个字符串形式传入参数名称。这在调试过程中提供了非常有用的信息,因为编码人员知道哪个参数为空。如果您的源不可用(或者如果异常跟踪是由未安装调试符号的最终用户提交的),否则可能无法确定实际发生的事情。对于其他异常类型,您还可以指定哪个变量为null,这可能是非常有用的信息。
  2. 捕获null取消引用是CLR可以执行的最昂贵的操作之一,如果您的代码抛出大量的NullReferenceExceptions,这可能会严重影响性能。测试无效并做一些其他事情(甚至抛出异常!)是一个更便宜的操作。 (类似的原理是,如果你声明与醒目的NRE的明确意图的catch块,你做错了什么别的地方,你应该有解决它,而不是使用try/catch语句。追赶的NRE应该永远是不可或缺的)任何算法的一部分。

话虽这么说,不乱丢你的代码的地方,你不要指望空值空测试。但是如果有可能引用变量为空(例如,如果引用是由外部代码提供的话),那么你应该总是测试。

+0

这是一个处理空对象/指针的好(平衡)方法。从C++的角度来看,这篇文章给出了一个有趣的观点来看待过多的空检查。 [空指针检查 - 它是软件开发的灵丹妙药](https://cognitivewaves.wordpress.com/2014/12/26/null-pointer-checks) – 2015-03-22 10:59:04

1

我已经超过10年的编程Java和我不记得一个单一的时间我已经明确地试图抓住一个空指针异常。

有时候变量有时候会是空的(例如对象的可选属性),在这种情况下,我需要测试null(obj.attr!= null),或者我希望变量不是任何时候都是null(在这种情况下,null表示代码中其他地方的错误)。如果我正在编写其参数(String s)为空的方法(称为isUpperCase),那么我显式测试null,然后抛出IllegalArgumentException。

永远做什么,默默地从零恢复。如果一个方法应该返回一个字符串中大写字符的数量并且传递的参数为null,那么我将永远不会“隐藏”它,通过静默地返回0来掩盖潜在的错误。

0

Personnally(做C++),除非有向我保证,我的指针没有nullptr强烈的合同,我一直对其进行测试,并返回错误,或者,如果这是允许不返回。

0

在Objective-C,你可以放心地做零,你可以用一个非空做和零最终被一个空操作,任何东西。事实证明,这非常方便。少了一些样板空白检查,并且例外情况是为真正特殊情况保留的。或者这会被认为是草率编码?