Null Object Pattern in C#

I recently just learned about the Null Object Pattern in C# through Pluralsight. I think it is straightforward to implement. As usual, the tricky part I believe is knowing when to use it or why you would use it.

The basic goal of the Null Object Pattern

This pattern aims to decrease or greatly minimize the need for null checking code in parts of a code base. I think no one wants writing boilerplate like the if clause below.

public YourMethod(someVariable)
{
  if(someVariable != null)
  {
     CallSomeMethod(someVariable)
  }
}

 

Another main goal of this pattern is to eliminate or decrease the occurrence of the dreaded null-reference exception during an application’s run-time.

High level overview of the Pattern 

Overview of Null Object Pattern in C#

The image above shows what the pattern is conceptually. Imagine you have an abstraction containing only a method signature, this abstraction could be an Interface or an Abstract Class. This then has a real implementation(s) and a null object implementation(s). The key here is this:


To client code, a real object and a null object can be treated equally.

Because the client code is only referencing the abstraction, the implementation (Real or Null) is not its concern.

Implementing the Null Object Pattern in C

Here is a Github repo that illustrates the pattern’s basic implementation.

Some things to take note when using the pattern:

  • When working with others, your team should know what parts of your project uses the null object pattern – or else other team members might use magic numbers or perform manual null checks instead
  • Client code that uses the null object should agree on what the null behavior is – problems could arise if different clients expect something unique to them for null behavior. If clients are like this, it is better to have different null object implementations
  • You usually do not want to use the null object pattern for error handling – actual errors should be handled correctly (e.g. throw an exception quick), using the null object pattern when errors happen can potentially create difficult debugging scenarios later on