avoiding null reference exceptions

后端 未结 15 991
天命终不由人
天命终不由人 2020-11-28 08:50

Apparently the vast majority of errors in code are null reference exceptions. Are there any general techniques to avoid encountering null reference errors?

Unless I

相关标签:
15条回答
  • 2020-11-28 09:13

    Good code analysis tools can help here. Good unit tests can also help if you're using tools that consider null as a possible path through your code. Try throwing that switch in your build settings that says "treat warnings as errors" and see if you can keep the # of warnings in your project = 0. You may find the warnings are telling you a lot.

    One thing to keep in mind is that it may be a good thing that you are throwing a null - reference exception. Why? because it may mean that code that should have executed did not. Initializing to default values is a good idea, but you should be careful that you don't end up hiding a problem.

    List<Client> GetAllClients()
    {
        List<Client> returnList = new List<Client>;
        /* insert code to go to data base and get some data reader named rdr */
       for (rdr.Read()
       {
          /* code to build Client objects and add to list */
       }
    
       return returnList;
    }
    

    Alright, so this may look ok, but depending on your business rules, this may be a problem. Sure, you'll never throw a null reference, but maybe your User table should never be empty? Do you want your app to be spinning in place, generating support calls from users saying "it's just a blank screen", or do you want to raise an exception that might get logged somewhere and raise an alert quickly? Don't forget to validate what you're doing as well as 'handling' exceptions. This is one of the reasons why some are loathe to take nulls out of our languages... it makes it easier to find the bugs even though it may cause some new ones.

    Remember: Handle exceptions, don't hide them.

    0 讨论(0)
  • 2020-11-28 09:15

    One of the most common null reference errors that I've seen is from strings. There will be a check:

    if(stringValue == "") {}
    

    But, the string is really null. It should be:

    if(string.IsNullOrEmpty(stringValue){}
    

    Also, you could be overly cautious and check an object isn't null before you attempt to access members/methods of that object.

    0 讨论(0)
  • 2020-11-28 09:20

    Using Null Object Patterns is key here.

    Make sure that you require collections to be empty in the case when they're not populated, rather than null. Using a null collection when an empty collection would do is confusing and often unnecessary.

    Finally, I make my objects assert for non-null values upon construction wherever possible. That way I'm in no doubt later on as to whether values are null, and only have to perform null checks where essential. For most of my fields and parameters I can assume that values are not null based on previous assertions.

    0 讨论(0)
  • 2020-11-28 09:23

    One way is to use the Null Value Objects (aka the Null Object Pattern) where possible. There are more details here

    0 讨论(0)
  • 2020-11-28 09:28

    In addition to the above (Null Objects, Empty Collections), there are some general techniques, namely Resource Acquisition is Initialization (RAII) from C++ and Design By Contract from Eiffel. These boil down to:

    1. Initialize variables with valid values.
    2. If a variable can be null, then either check for null and treat it as a special case or expect a null reference exception (and deal with that). Assertions can be used to test for contract violations in development builds.

    I've seen a lot of code that looks like this:

    if ((value != null) && (value.getProperty() != null) && ... && (...doSomethingUseful())

    A lot of the time this is completely unnecessary and most of the tests could be removed with stricter initialization and tighter contract definitions.

    If this is a problem in your code base then it is necessary to understand in each case what the null represents:

    1. If the null represents an empty collection, use an empty collection.
    2. If the null represents an exceptional case, throw an Exception.
    3. If the null represents an accidentally uninitialized value, explicitly initialize it.
    4. If the null represents a legitimate value, test for it - or even better use a NullObject that performs a null op.

    In practice this standard of clarity at the design level is non-trivial and requires effort and self-discipline to apply consistently to your code base.

    0 讨论(0)
  • 2020-11-28 09:29

    Really if in your language there are null values, it's bound to happen. The null reference errors come from errors in application logic - so unless you can avoid all of those your're bound to hit some.

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