When is handling a null pointer/reference exception preferred over doing a null check?

和自甴很熟 提交于 2020-01-24 12:42:26

问题


I have an odd question that I have always thought about, but could never see a practical use for. I'm looking to see if there would be enough justification for this.

When is handling a null pointer/reference exception preferred over doing a null check? If at all.

This applies to any language that has to deal with null pointers/references which has exception handling features.

My usual response to this would be to perform a null check before doing anything with the pointer/reference. If non-null, continue like normal and use it. If null, handle the error or raise it.

i.e., (in C#)

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

However if we were not to do the check and just blindly use it, an exception would be raised.

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

Being an exception, we could certainly catch it so nothing is stopping us from doing this (or is there?):

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

Now I admit, it's not the cleanest code, but it's no less working code and I wouldn't do this normally. But is there a design pattern or something where doing this is useful? Perhaps more useful than doing the straight up, null check beforehand.

The only cases where I can imagine this might be useful is in a multi-threaded environment where an unprotected shared variable gets set to null too soon. But how often does that happen? Good code that protects the variables wouldn't have that problem. Or possibly if one was writing a debugger and wanted the exception to be thrown explicitly only to wrap it or whatnot. Maybe an unseen performance benefit or removes the need for other things in the code?

I might have answered some of my questions there but is there any other use to doing this? I'm not looking for, "do this just because we can" kinds of examples or just poorly written code, but practical uses for it. Though I'll be ok with, "there's no practical use for it, do the check."


回答1:


The problem is that all null pointer exceptions look alike. Any accounting that could be added to indicate which name tripped the exception can't be any more efficient than just checking for null in the first place.




回答2:


If you expect the value to not be null, then there is no point in doing any checks. But when accepting arguments, for example, it makes sense to test the arguments that you require to be non-null and throw ArgumentNullExceptions as appropriate.

This is preferred for two reasons:

  1. Typically you would use the one-string form of the ArgumentNullException constructor, passing in the argument name. This gives very useful information during debugging, as now the person coding knows which argument was null. If your source is not available to them (or if the exception trace was submitted by an end user with no debug symbols installed) it may otherwise be impossible to tell what actually happened. With other exception types you could also specify which variable was null, and this can be very helpful information.
  2. Catching a null dereference is one of the most expensive operations that the CLR can perform, and this could have a severe performance impact if your code is throwing a lot of NullReferenceExceptions. Testing for nullity and doing something else about it (even throwing an exception!) is a cheaper operation. (A similar principle is that if you declare a catch block with the explicit intent of catching NREs, you are doing something wrong somewhere else and you should fix it there instead of using try/catch. Catching NREs should never be an integral part of any algorithm.)

That being said, don't litter your code with null tests in places you don't ever expect null values. But if there is a chance a reference variable might be null (for example if the reference is supplied by external code) then you should always test.




回答3:


I've been programming Java for more than 10 years, and I can't remember a single time I've explicitly tried to catch a null pointer exception.

Either the variable is expected to be null sometimes (for example an optional attribute of an object), in which case I need to test for null (obj.attr != null), or I expect the variable to be not null at all times (in which case a null indicates a bug elsewhere in the code). If I'm writing a method (say isUpperCase) whose argument (String s) is null, I explicitly test for null and then throw an IllegalArgumentException.

What I never ever do, is silently recover from a null. If a method should return the number of upper case characters in a string and the passed argument was null, I would never "hide" it by silently return 0 and thus masking a potential bug.




回答4:


Personnally (doing C++), unless there is a STRONG contract that assures me that my pointers are not nullptr, I always test them, and return error, or silently return if this is allowed.




回答5:


In Objective-C you can safely do anything with nil you can do with a non-nil and the nil ends up being a noop. This turns out to be surprisingly convenient. A lot less boilerplate null checking, and exceptions are reserved for truly exceptional circumstances. Or would that be considered sloppy coding?



来源:https://stackoverflow.com/questions/4374611/when-is-handling-a-null-pointer-reference-exception-preferred-over-doing-a-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!