25

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 am mistaken, I am aware that in languages such as F# is it not possible to have a null value. But thats not the question, I'm asking how to avoid null reference errors in languages such as C#.

Nippysaurus
  • 19,402
  • 18
  • 71
  • 124
  • 2
    The answer is to not play around with `null`. Don't shoehorn it in as an "error code", don't toss it about like it's a real object, and in fact, don't even *think* about writing `x = null` *at all* unless you can justify *why* you're using it in this particular case. Oh yeah, and if you're making calls to code you don't control, check the documentation and see if it can return null too. And make sure to check for it if it can. – Anon. Dec 22 '09 at 00:22
  • 1
    "the vast majority of errors in code are null reference exceptions" - just curious, where did you get that statistic from? – Ragepotato Dec 22 '09 at 00:22
  • @Ragepotato: I wrote "apparently" because it was just told to me, I never claimed for it to be a statistic. It was in a talk by some Microsoft employee who was hilighting the benefits of F#. – Nippysaurus Dec 22 '09 at 00:30
  • 1
    As a Microsoft employee who works on F#, I can say definitively that it is _not_ true that "the vast majority of errors in code are null reference exceptions". – Brian Dec 22 '09 at 00:33
  • @Brian: well then this guy was feeding us some bs hey :) – Nippysaurus Dec 22 '09 at 00:34
  • (That said, 'null' is 'the billion dollar mistake', and many languages force you to accept 'null' as a value for a data type even when you don't want it. Errors resulting from null are typically easy to identify, fix, and guard against, but they're niggling and they're everywhere, and the aforementioned 'billion dollars' is presumably due to nickel-and-diming everyone for the past couple decades.) – Brian Dec 22 '09 at 00:37
  • Almost all cases of `NullReferenceException` are the same. Please see "[What is a NullReferenceException in .NET?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net)" for some hints. – John Saunders Apr 04 '14 at 17:31
  • Tony Hoare introduced Null references in ALGOL W back in 1965 “simply because it was so easy to implement”, says Mr. Hoare. He talks about that decision considering it “my billion-dollar mistake” http://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare – Luis Perez Mar 08 '16 at 01:45

16 Answers16

32

When a null reference exception is displayed to the user, this indicates a defect in the code resulting from an error on the part of the developer. Here are some ideas on how to prevent these errors.

My top recommendation for people who care about software quality, and are also using the.net programming platform, is to install and use Microsoft code contracts ( http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx ). It includes capabilities to do run-time checking and static verification. The essential capability to build these contracts into your code is being included in the 4.0 version of the.net framework. If you are interested in code quality, and it sounds like you are, you may really enjoy using Microsoft code contracts.

With Microsoft code contracts, you can guard your method from null values by adding preconditions like this "Contract.Requires(customer != null);". Adding a precondition like this is equivalent to the practice recommended by many others in their comments above. Prior to code contracts, I would have recommended you do something like this

if (customer == null) {throw new ArgumentNullException("customer");}

Now I recommend

Contract.Requires(customer != null);

You can then enable the run-time checking system which will catch these defects as early as possible, leading you towards diagnosis and correction of the defective code. But don't let me give you the impression that code contracts are simply a fancy way to replace argument null exceptions. They are much more powerful than that. With Microsoft code contracts, you can also run the static checker, and ask it to investigate possible sites in your code where null reference exceptions might occur. The static checker requires a bit more experience to use easily. I would not recommend it first for beginners. But feel free to try it out and see for yourself.

RESEARCH ON THE PREVALENCE OF NULL REFERENCE ERRORS

There has been some debate in this thread on whether null reference errors are a significant problem. A long-winded answer is below. For people who don't want to wade through that, I will summarize.

  • Microsoft's leading researchers in program correctness on the Spec# and code contracts projects believe it is a problem worth addressing.
  • Dr. Bertrand Meyer and the team of software engineers at ISE, who developed and support the Eiffel programming language, also believe it is a problem worth addressing.
  • In my own commercial experience developing ordinary software, I have seen null reference errors often enough, that I would like to address the problem in my own products and practices.

For years, Microsoft has invested in research designed to improve software quality. One of their efforts was the Spec# project. One of the most exciting developments in my opinion with the.net 4.0 framework, is the introduction of Microsoft code contracts, which is an outgrowth of the earlier work done by the Spec# research team.

Regarding your remark "the vast majority of errors in code are null reference exceptions", I believe it is the qualifier "the vast majority" that will cause some disagreements. The phrase "Vast majority" suggests that perhaps 70-90% of faults have a null reference exception as the root cause. This seems far too high to me. I prefer to quote from the research of the Microsoft Spec#. In their article The Spec# programming system: An overview, by Mike Barnett, K. Rustan M. Leino, and Wolfram Schulte. In CASSIS 2004, LNCS vol. 3362, Springer, 2004, they wrote

1.0 Non-Null Types Many errors in modern programs manifest themselves as null-dereference errors, suggesting the importance of a programming language providing the ability to discriminate between expressions that may evaluate to null and those that are sure not to (for some experimental evidence, see [24, 22]). In fact, we would like to eradicate all null dereference errors.

This is a likely source for people at Microsoft who are familiar with this research. This article is available at the Spec# site.

I've copied references 22 and 24 below, and included the ISBN for your convenience.

  • Manuel Fahndrich and K. Rustan M. Leino. Declaring and checking non-null types in an object-oriented language. In Proceedings of the 2003 ACM Conference on Object-Oriented Programming, Systems, Languages, and Applications, OOPSLA 2003, volume 38, number 11 in SIGPLAN Notices, pages 302–312. ACM, November 2003. isbn = {1-58113-712-5},

  • Cormac Flanagan, K. Rustan M. Leino, Mark Lillibridge, Greg Nelson, James B. Saxe, and Raymie Stata. Extended static checking for Java. In Proceedings of the 2002 ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI), volume 37, number 5 in SIGPLAN Notices, pages 234–245. ACM, May 2002.

I reviewed these references. The first reference indicates some experiments they did reviewing their own code for possible null reference defects. Not only did they find several, but in many cases, the identification of a potential null reference indicated a broader problem with the design.

The second reference does not provide any specific evidence for the assertion that null reference errors are problem. But the authors do state that in their experience, these null reference errors are significant source of software defects. The paper then proceeds to explain how they try to eradicate these defects.

I also remembered seeing something about this in an announcement from ISE on a recent release of Eiffel. They refer to this issue as "void safety", and like so many things inspired or developed by Dr. Bertrand Meyer, they have an eloquent and educational description of the problem and how they go about preventing it in their language and tools. I recommend you read their article http://doc.eiffel.com/book/method/void-safety-background-definition-and-tools to learn more.

If you want to learn more about Microsoft code contracts, there are tons of articles that have arisen recently. You can also check my blog at http: SLASH SLASH codecontracts.info which is primarily devoted to conversations about software quality through the use of programming with contracts.

John Saunders
  • 157,405
  • 24
  • 229
  • 388
David Allen
  • 344
  • 2
  • 2
  • Stephen's comment: not using it due to lack of async support. http://blog.stephencleary.com/2011/01/simple-and-easy-code-contracts.html. Quote: "It's a shame... it's been all but abandoned now". – Serge Pavlov Oct 22 '18 at 14:25
21

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.

richj
  • 7,409
  • 2
  • 30
  • 48
7

You don't.

Or rather, there's nothing special to do to try to 'prevent' NREs in C#. For the most part an NRE is just some type of logic error. You can firewall these off at interface boundaries by checking parameters and having lots of code like

void Foo(Something x) {
    if (x==null)
        throw new ArgumentNullException("x");
    ...
}

all over the place (much of the .Net Framework does this), so that when you do screw up, you get a slightly more informative diagnostic (the stack trace is even more valuable, though, and an NRE provides that too). But you still just end up with an exception.

(Aside: Exceptions like these - NullReferenceException, ArgumentNullException, ArgumentException, ... - typically should not be caught by the program, but rather just means "developer of this code, there is a bug, please fix it". I refer to these as a 'design time' exceptions; contrast these with true 'run time' exceptions that happen as a result of the run time environment (e.g. FileNotFound) and are intended to potentially be caught and handled by the program.)

But at the end of the day, you just have to code it right.

Ideally the majority of NREs would never happen because 'null' is a nonsensical value for many types/variables, and ideally the static type system would disallow 'null' as a value for those particular types/variables. Then the compiler would prevent you from introducing this type of accidental error (ruling out certain classes of errors are what compilers and type systems are best at). This is where certain languages and type systems excel.

But without those features, you just test your code to ensure you don't have code paths with this type of error (or possibly use some outside tools that can do extra analysis for you).

Brian
  • 113,581
  • 16
  • 227
  • 296
  • 4
    +1 for "design time" exceptions -- interesting distinction. I've had arguments with people at work about exceptions where I've said the same thing. The person says "exceptions are too slow", then I say "but if we code it right then we won't trigger or handle any of these exceptions anyway!" – Mark Simpson Dec 22 '09 at 01:12
5

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.

Brian Agnew
  • 254,044
  • 36
  • 316
  • 423
5

You can easily check for a null reference before it causes an exception, but usually that is not the real problem, so you would just end up throwing an exception anyway as the code can't really continue without any data.

Often the main problem isn't the fact that you have a null reference, but that you got a null reference in the first place. If a reference is not supposed to be null, you shouldn't get past the point where the reference is initialised without having a proper reference.

Guffa
  • 640,220
  • 96
  • 678
  • 956
4

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.

Jeremy Raymond
  • 5,377
  • 3
  • 28
  • 32
4

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.

Jim Schubert
  • 19,627
  • 5
  • 56
  • 67
3

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

Preet Sangha
  • 61,126
  • 17
  • 134
  • 202
2

Appropriate use of structured exception handling can help avoid such errors.

Also, unit testing can help you make sure your code behaves as expected, including ensuring that values are not null when they're not supposed to be.

Andy West
  • 11,584
  • 2
  • 32
  • 49
2

One of the simplest ways to avoid NullReferenceExceptions is to aggressively check for null references in your class constructors/methods/property setters and draw attention to the problem.

E.g.

public MyClass
{
   private ISomeDependency m_dependencyThatWillBeUsedMuchLater 

   // passing a null ref here will cause 
   // an exception with a meaningful stack trace    
   public MyClass(ISomeDependency dependency)
   {
      if(dependency == null) throw new ArgumentNullException("dependency");

      m_dependencyThatWillBeUsedMuchLater = dependency;
   }

   // Used later by some other code, resulting in a NullRef
   public ISomeDependency Dep { get; private set; }
}

In the above code, if you pass a null ref, you will find out immediately that the calling code is using the type incorrectly. If there was no null reference check, the error can be obscured in many different ways.

You'll notice that the .NET framework libraries nearly always fail early and often if you provide null references where it's invalid to do so. Since the exception thrown explicitly says "you messed up!" and tells you why, it makes detecting and correcting defective code a trivial task.

I've heard complaints from some developers who say this practice is overly verbose and redundant as a NullReferenceException is all you need, but in practice I find it makes a big difference. This is especially the case if the call stack is deep and/or the parameter is stored and its use is deferred until later (perhaps on a different thread or obscured in some other way).

What would you rather have, an ArgumentNullException at the entry method, or an obscure error in the guts of it? The further you move away from the source of an error, the harder it is to trace it.

Mark Simpson
  • 22,573
  • 2
  • 41
  • 42
2

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.

Jim L
  • 2,187
  • 16
  • 20
1

Plain Code Solution

You could always create a struct that helps catch null reference errors earlier by marking variables, properties, and parameters as "not nullable". Here's an example conceptually modeled after the way Nullable<T> works:

[System.Diagnostics.DebuggerNonUserCode]
public struct NotNull<T> where T : class
{
    private T _value;

    public T Value
    {
        get
        {
            if (_value == null)
            {
                throw new Exception("null value not allowed");
            }

            return _value;
        }
        set
        {
            if (value == null)
            {
                throw new Exception("null value not allowed.");
            }

            _value = value;
        }
    }

    public static implicit operator T(NotNull<T> notNullValue)
    {
        return notNullValue.Value;
    }

    public static implicit operator NotNull<T>(T value)
    {
        return new NotNull<T> { Value = value };
    }
}

You would use very similar to the same way you would use Nullable<T>, except with the goal of accomplishing exactly the opposite - to not allow null. Here are some examples:

NotNull<Person> person = null; // throws exception
NotNull<Person> person = new Person(); // OK
NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null

NotNull<T> is implicitly casted to and from T so you can use it just about anywhere you need it. For example you can pass a Person object to a method that takes a NotNull<Person>:

Person person = new Person { Name = "John" };
WriteName(person);

public static void WriteName(NotNull<Person> person)
{
    Console.WriteLine(person.Value.Name);
}

As you can see above as with nullable you would access the underlying value through the Value property. Alternatively, you can use explicit or implicit cast, you can see an example with the return value below:

Person person = GetPerson();

public static NotNull<Person> GetPerson()
{
    return new Person { Name = "John" };
}

Or you can even use it when the method just returns T (in this case Person) by doing a cast. For example the following code would just just like the code above:

Person person = (NotNull<Person>)GetPerson();

public static Person GetPerson()
{
    return new Person { Name = "John" };
}

Combine with Extension

Combine NotNull<T> with an extension method and you can cover even more situations. Here is an example of what the extension method can look like:

[System.Diagnostics.DebuggerNonUserCode]
public static class NotNullExtension
{
    public static T NotNull<T>(this T @this) where T : class
    {
        if (@this == null)
        {
            throw new Exception("null value not allowed");
        }

        return @this;
    }
}

And here is an example of how it could be used:

var person = GetPerson().NotNull();

GitHub

For your reference I made the code above available on GitHub, you can find it at:

https://github.com/luisperezphd/NotNull

Luis Perez
  • 26,159
  • 10
  • 76
  • 77
0

You can use Null Object pattern and Special Case pattern in cases when there can be a legitimate object which can substitute null.

In cases when such object cannot be constructed, because simply there is no way to implement its mandatory operations, you can rely on empty collections, such as in Map-Reduce Queries.

Another solution is the Option functional type, which is the collection with zero or one elements. In that way, you will have the opportunity to skip the operation that cannot be performed.

These are the options that can help you write code without having any null references and any null checks.

Zoran Horvat
  • 9,447
  • 3
  • 26
  • 39
0

Tools that can help

There are also several libraries that can help. Microsoft Code Contracts was mentioned above.

Some other tools include Resharper which can provide you with warnings while you are writing code, especially if you use their attribute: NotNullAttribute

There's also PostSharp which will allow you to just use attributes like this:

public void DoSometing([NotNull] obj)

By doing that and making PostSharp part of your build process obj will be checked for null at runtime. See: PostSharp null check

The Fody code-weaving project has a plug-in for implementing null guards.

Community
  • 1
  • 1
Luis Perez
  • 26,159
  • 10
  • 76
  • 77
0

Successfully avoiding null without proper “else case” means that now your program won’t fail, but it won’t correct either. Optional can’t help you either unless whole java api returns optional, but by then, you are forced to check for nothing everywhere as if checking null everywhere. It makes no difference after all.

In the future people may invent another object “Falsable” to avoid returning false without checking! LOL

Only understanding the logic and check as need can help you. Not Optional. It is just false safety.

-1

NullReferenceException can be shown when a method is not found in the assembly,for ex m0=mi.GetType().GetMethod("TellChildToBeQuiet") where the assembly is SportsMiniCar,mi is the instance of MiniVan and TellChildToBeQuiet is a method in the assembly. We can avoid this by seeing that this assembly Version 2.0.0.0 containing the above method is placed in the GAC. example:Invoking methods with parameters:`

enter code here

using System;
using System.Rwflection;
using System.IO;
using Carlibraries;
namespace LateBinding
{
public class program
{
   static void Main(syring[] args)
   {
         Assembly a=null;
         try
         {
              a=Assembly.Load("Carlibraries");
         }
         catch(FileNotFoundException e)
         {
               Console.Writeline(e.Message);
               Console.ReadLine();
               return;
         }
         Type miniVan=a.GetType("Carlibraries.MiniVan");
         MiniVan mi=new MiniVan();
         mi.TellChildToBeQuiet("sonu",4);
         Console.ReadLine();
       }
   }
   }

Remember updating MiniSportsCar Assembly with TellChildToBeQuiet(string ChildName,int count)