Click here to Skip to main content
15,881,204 members
Articles / Programming Languages / C#
Article

Avoiding null in C#

Rate me:
Please Sign up or sign in to vote.
3.61/5 (25 votes)
20 Jun 2004CC (ASA 2.5)3 min read 289.1K   36   33
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:

C#
// 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:

C#
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:

C#
// 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


Written By
Team Leader
United Kingdom United Kingdom
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.

Comments and Discussions

 
QuestionWould it be useful if there was a way to prevent assigning null to a variable? Pin
Luis Perez ----- (Simply Good Code)8-Mar-16 4:24
Luis Perez ----- (Simply Good Code)8-Mar-16 4:24 
GeneralMy vote of 4 Pin
MohammadIqbal1-Oct-11 0:07
MohammadIqbal1-Oct-11 0:07 
GeneralCoalesce? Pin
hoodaticus8-Jun-11 10:21
hoodaticus8-Jun-11 10:21 
GeneralRe: Coalesce? Pin
Dr Herbie8-Jun-11 18:24
Dr Herbie8-Jun-11 18:24 
QuestionWhat to do with recursion? Pin
Csupor Jenő18-Aug-06 5:42
Csupor Jenő18-Aug-06 5:42 
AnswerRe: What to do with recursion? [modified] Pin
Dr Herbie18-Aug-06 5:58
Dr Herbie18-Aug-06 5:58 
GeneralTypo obscures message Pin
pdelmonte6-Oct-05 14:37
pdelmonte6-Oct-05 14:37 
GeneralRe: Typo obscures message Pin
Dr Herbie6-Oct-05 21:34
Dr Herbie6-Oct-05 21:34 
GeneralI need the code of a memory game Pin
manuel_spain3-Jun-05 11:45
manuel_spain3-Jun-05 11:45 
GeneralRe: I need the code of a memory game Pin
Adam Clauss5-Jul-05 8:38
Adam Clauss5-Jul-05 8:38 
QuestionHow can we check Date Values are null? Pin
dfjdshfksd8-May-05 2:40
sussdfjdshfksd8-May-05 2:40 
AnswerRe: How can we check Date Values are null? Pin
S. Senthil Kumar8-May-05 3:17
S. Senthil Kumar8-May-05 3:17 
AnswerRe: How can we check Date Values are null? Pin
Dr Herbie8-May-05 21:24
Dr Herbie8-May-05 21:24 
QuestionHow about a static field as a placeholder for null? Pin
Lornhold3-Jul-04 16:51
Lornhold3-Jul-04 16:51 
GeneralI'm pleased with responses Pin
Dr Herbie28-Jun-04 21:53
Dr Herbie28-Jun-04 21:53 
GeneralTwo problems with this approach Pin
Martin Friedrich28-Jun-04 6:03
Martin Friedrich28-Jun-04 6:03 
GeneralRe: Two problems with this approach Pin
Dr Herbie28-Jun-04 6:19
Dr Herbie28-Jun-04 6:19 
Martin Friedrich wrote:
singleton pattern or a static instance for the NullObject

That is actually what I had intended to mean, for reasons of memory usage (which is the context I mentioned the NullObject) but I should have been explicit on that one.


Martin Friedrich wrote:
Woolf explicitly names situations where one can live with stubs or stub-like behaviour

I hate to sound arrogant, but I disagree with Woolf -- I do not believe there should ever be stub-like behaviour; it confises programmers (IMHO Smile | :) )



Martin Friedrich wrote:
Typically, null is assigned to variables to indicate uninitialized or unassigned state, including detaching an instance from a variable, or to indicate a failure of some operation (for example, malloc(3)).

Aargh! No one using .NET should ever use a null to indicate a failure, you ahould use an Exception. And malloc? I haven't used malloc for years!




Dr Herbie
Remember, half the people out there have below average IQs.
General... more Pin
Dr Herbie28-Jun-04 21:46
Dr Herbie28-Jun-04 21:46 
GeneralRe: ... more Pin
Martin Friedrich29-Jun-04 6:20
Martin Friedrich29-Jun-04 6:20 
GeneralRe: Two problems with this approach Pin
Michael D. Bray1-Jul-04 5:19
sussMichael D. Bray1-Jul-04 5:19 
GeneralRe: Two problems with this approach Pin
Dan Mordechay26-Mar-12 5:10
Dan Mordechay26-Mar-12 5:10 
Questionis it a purist word ? Pin
Anonymous27-Jun-04 2:42
Anonymous27-Jun-04 2:42 
AnswerRe: is it a purist word ? Pin
Dr Herbie28-Jun-04 6:08
Dr Herbie28-Jun-04 6:08 
GeneralString.IsNullOrEmpty() Pin
fabrice.marguerie22-Jun-04 1:12
fabrice.marguerie22-Jun-04 1:12 
GeneralisNull func could help Pin
worldspawn21-Jun-04 13:11
worldspawn21-Jun-04 13:11 

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

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