Click here to Skip to main content
Licence CC (ASA 2.5)
First Posted 20 Jun 2004
Views 201,385
Bookmarked 33 times

Avoiding null in C#

By | 20 Jun 2004 | Article
Make Code More Robust by Avoiding nulls in C#

Introduction

The null keyword is a special case for a variable value. Code robustness can be improved by reducing the number of special cases that have to be dealt with. In this article I shall explain how to reduce the number of times you use the null keyword and thus (hopefully) improve the stability of your code.

Background

I come from a mainly C++ background. I C++ you can get so used to having to handle NULL pointers that doing a check (if (MyClass != NULL) ) become second nature. After converting to C#, however, I realized that it was time to mend my ways. Having to check for null every time I want to access a string or class clutters code and makes it more likely that other programmers in the future will end up getting lots of NullReferenceExceptions to deal with.

Strings

With strings there are normally two special cases that have to be checked: null strings and empty strings. Things are generally easier if we can reduce this to just one special case of empty strings.

When defining a string in a class, don't initialise it to null. Instead, initialise it to the constant string.Empty . This means that whenever another programmer accesses this string through a property, they don't have to worry about getting a null value back.

However, you must also cope with the possibility that the user of the object passes a null back in to the property. Therefore you must catch this and convert it to a null .

For Example, the first of the following classes uses null while the second does not:

// A naive, unstable class that uses nulls
public class MyUnstableStringClass
{
  // Private string variable, initialised to null
  private string mMyString = null;
  
  // Simplistic property for accessing and modifying string.
  public string MyString
  {
    get
    {
      return mMyString;
    }
    set
    {
      mMyString = value;
    }
  }
}

// A stable class that doesn't use nulls.
public class MyStableStringClass
{
  // Private string variable, initialised to empty string.
  private string mMyString = string.Empty;
  
  // Public property for accessing and modifying string.
  public string MyString
  {
    get
    {
      return mMyString;
    }
    set
    {
      if (value != null)
      {
        mMyString = value;
      }
      else
      {
        mMyString = string.Empty;
      }
    }
  }    
}
    

OK, so the second class has a few extra lines of code. That's the penalty for writing stable software, but it's not much. The advantage comes when the classes are used:

  MyUnstableStringClass unstable = new MyUnstableStringClass();
  MyStableStringClass stable = new MyStableStringClass();
  
  // Check for empty strings
  if (stable.MyString.Length == 0)
    Console.WriteLine("Stable string is empty");
    
  // THIS WILL THROW AN EXCEPTION (NullReferenceException)
  if (unstable.MyString.Length == 0)
    Console.WriteLine("Unstable string is empty");

  // To prevent crash for unstable
  if ((unstable.MyString != null) && (unstable.MyString.Length == 0))
    Console.WriteLine("Unstable string is empty");

NOTE: To check for empty strings, use the Length property, rather than comparing to the empty string. This is much faster than a string comparison.

You can see here that the MyStableStringClass.MyString property doesn't need a null-check to prevent a crash. This reduction in code required to use the class will more than make up for the additional few lines required within the class property. It will also help other programmers who may well forget to check for null.

Classes

So far, so good. But strings are pretty simplistic; how can we use this for classes?

If you simply ensure that a class is properly initialised and that none of the properties return null references, then we can use the same method as we used for strings in the first section of this article:

// A complex class containing properties that return simple classes
public class MyComplexClass
{
  // Aggregated MyStableStringClass, available as a property
  private MyStableStringClass mInternalClass = new MyStableStringClass();
  
  // Access to the aggregated class
  public MyStableStringClass InternalStringClass
  {
    get
    {
      return mInternalClass;
    }
    set
    {
      // Replace nulls with a new instance
      if (value != null)
      {
        mInternalClass = value;
      }
      else
      {
        // If this class implemented IDisposable,
        // we would call Dispose() here before re-initialising
        mInternalClass = new MyStableStringClass();
      }
    }
  }
}

As you can see, we initialise the aggregated class to a new instance (same as we set the string to be string.Empty in the MyStableStringClass in the first section of this article). In the InternalStringClass property set method, we replace null references with new instances of the class. Now whenever we access the MyComplexClass.InternalStringClass property, we never have to remember to check for null; we can even go straight to MyComplexClass.InternalStringClass.MyString and never have to worry that is might not exist.

Unfortuantely, there is a downside - you end up using more memory with this method. All classes are always instantiated, and this can become an issue in a system with a large number of classes. Fortunately, a more advanced solution has already been made: the NullObject (PDF file) pattern shows us how to create an equivalent of the string.Empty constant for a class.

I won't go into the details of how to implement the NullObject pattern, I'll save that for another, more advanced article. Unless, of course, you feel inspired to write one first ...

Any comments are welcome. Any spelling mistakes are purely the readers reasonability.

History

  • 19/06/2004 -- First release.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License

About the Author

Dr Herbie

Team Leader

United Kingdom United Kingdom

Member

After ten years studying biology and evolution, I threw it all away and became a fully paid up professional programmer. Since 1990 I have done C/C++ Windows 3.1 API, Pascal, Win32, MFC, OOP, C#, etc, etc.
 
PS. In the picture, I'm the one in blue. On the right.
 


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 4 PingroupMohammadIqbal0:07 1 Oct '11  
GeneralCoalesce? Pinmemberhoodaticus10:21 8 Jun '11  
GeneralRe: Coalesce? PinmemberDr Herbie18:24 8 Jun '11  
QuestionWhat to do with recursion? PinmemberCsupor Jeno5:42 18 Aug '06  
AnswerRe: What to do with recursion? [modified] PinmemberDr Herbie5:58 18 Aug '06  
GeneralTypo obscures message Pinmemberpdelmonte14:37 6 Oct '05  
GeneralRe: Typo obscures message PinmemberDr Herbie21:34 6 Oct '05  
GeneralI need the code of a memory game Pinmembermanuel_spain11:45 3 Jun '05  
GeneralRe: I need the code of a memory game PinmemberAdam Clauss8:38 5 Jul '05  
QuestionHow can we check Date Values are null? Pinsussdfjdshfksd2:40 8 May '05  
AnswerRe: How can we check Date Values are null? PinmemberS. Senthil Kumar3:17 8 May '05  
AnswerRe: How can we check Date Values are null? PinmemberDr Herbie21:24 8 May '05  
QuestionHow about a static field as a placeholder for null? PinsussLornhold16:51 3 Jul '04  
GeneralI'm pleased with responses PinmemberDr Herbie21:53 28 Jun '04  
GeneralTwo problems with this approach PinmemberMartin Friedrich6:03 28 Jun '04  
GeneralRe: Two problems with this approach PinmemberDr Herbie6:19 28 Jun '04  
General... more PinmemberDr Herbie21:46 28 Jun '04  
GeneralRe: ... more PinmemberMartin Friedrich6:20 29 Jun '04  
GeneralRe: Two problems with this approach PinsussMichael D. Bray5:19 1 Jul '04  
GeneralRe: Two problems with this approach PinmemberDan Mordechay5:10 26 Mar '12  
Questionis it a purist word ? PinsussAnonymous2:42 27 Jun '04  
AnswerRe: is it a purist word ? PinmemberDr Herbie6:08 28 Jun '04  
GeneralString.IsNullOrEmpty() Pinmembernbenin1:12 22 Jun '04  
GeneralisNull func could help Pinmemberworldspawn13:11 21 Jun '04  
GeneralRe: isNull func could help PinmemberDr Herbie21:30 21 Jun '04  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120517.1 | Last Updated 21 Jun 2004
Article Copyright 2004 by Dr Herbie
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid