How much null checking is enough?

后端 未结 18 979
清酒与你
清酒与你 2021-01-30 01:10

What are some guidelines for when it is not necessary to check for a null?

A lot of the inherited code I\'ve been working on as of late has null-checks

相关标签:
18条回答
  • 2021-01-30 01:11

    I'd say it depends a little on your language, but I use Resharper with C# and it basically goes out of it's way to tell me "this reference could be null" in which case I add a check, if it tells me "this will always be true" for "if (null != oMyThing && ....)" then I listen to it an don't test for null.

    0 讨论(0)
  • 2021-01-30 01:12

    Older versions of Microsoft C++ (and probably others) did not throw an exception for failed allocations via new, but returned NULL. Code that had to run in both standard-conforming and older versions would have the redundant checking that you point out in your first example.

    It would be cleaner to make all failed allocations follow the same code path:

    if(obj==NULL)
        throw std::bad_alloc();
    
    0 讨论(0)
  • 2021-01-30 01:14

    It depends on the situation. The rest of my answer assumes C++.

    • I never test the return value of new since all the implementations I use throw bad_alloc on failure. If I see a legacy test for new returning null in any code I'm working on, I cut it out and don't bother to replace it with anything.
    • Unless small minded coding standards prohibit it, I assert documented preconditions. Broken code which violates a published contract needs to fail immediately and dramatically.
    • If the null arises from a runtime failure which isn't due to broken code, I throw. fopen failure and malloc failure (though I rarely if ever use them in C++) would fall into this category.
    • I don't attempt to recover from allocation failure. Bad_alloc gets caught in main().
    • If the null test is for an object which is collaborator of my class, I rewrite the code to take it by reference.
    • If the collaborator really might not exist, I use the Null Object design pattern to create a placeholder to fail in well defined ways.
    0 讨论(0)
  • 2021-01-30 01:14

    Whether to check for null or not greatly depends on the circumstances.

    For example in our shop we check parameters to methods we create for null inside the method. The simple reason is that as the original programmer I have a good idea of exactly what the method should do. I understand the context even if the documentation and requirements are incomplete or less than satisfactory. A later programmer tasked with maintenance may not understand the context and may assume, wrongly, that passing null is harmless. If I know null would be harmful and I can anticipate that someone may pass null, I should take the simple step of making sure that the method reacts in a graceful way.

    public MyObject MyMethod(object foo)
    {
      if (foo == null)
      {
        throw new ArgumentNullException("foo");
      }
    
      // do whatever if foo was non-null
    }
    
    0 讨论(0)
  • 2021-01-30 01:21

    At first, this seemed like a strange question: null checks are great and a valuable tool. Checking that new returns null is definitely silly. I'm just going to ignore the fact that there are languages that allow that. I'm sure there are valid reasons, but I really don't think I can handle living in that reality :) All kidding aside, it seems like you should at least have to specify that the new should return null when there isn't enough memory.

    Anyway, checking for null where appropriate leads to cleaner code. I'd go so far as to say that never assigning function parameters default values is the next logical step. To go even further, returning empty arrays, etc. where appropriate leads to even cleaner code. It is nice to not have to worry about getting nulls except where they are logically meaningful. Nulls as error values are better avoided.

    Using asserts is a really great idea. Especially if it gives you the option of turning them off at runtime. Plus, it is a more explicitly contractual style :)

    0 讨论(0)
  • 2021-01-30 01:22

    When you can specify which compiler is being used, for system functions such as "new" checking for null is a bug in the code. It means that you will be duplicating the error handling code. Duplicate code is often a source of bugs because often one gets changed and the other doesn't. If you can not specify the compiler or compiler versions, you should be more defensive.

    As for internal functions, you should specify the contract and make sure that contract is enforce via unit tests. We had a problem in our code a while back where we either threw an exception or returned null in case of a missing object from our database. This just made things confusing for the caller of the api so we went through and made it consistant throughout the entire code base and removed the duplicate checks.

    The important thing (IMHO) is to not have duplicate error logic where one branch will never be invoked. If you can never invoke code, then you can't test it, and you will never know if it is broken or not.

    0 讨论(0)
提交回复
热议问题