joydip_kanjilal
Contributor

How to use the null object pattern in .NET

how-to
Jan 05, 20235 mins
C#Microsoft .NETSoftware Development

Take advantage of the null object pattern in .NET to eliminate the need for null checks and avoid runtime errors in your applications.

You might often encounter null reference exceptions in your applications if null checks aren’t appropriately implemented. A null reference exception will abruptly terminate the execution of your program unless it is properly handled in your code. The null object pattern solves this problem, giving you an elegant way to handle null reference exceptions in your code.

This article discusses how we can implement the null object pattern in C# with relevant code examples wherever applicable. To work with the code examples provided in this article, you should have Visual Studio 2022 installed in your system. If you don’t already have a copy, you can download Visual Studio 2022 here.

Create a console application project in Visual Studio

First off, let’s create a .NET Core console application project in Visual Studio. Assuming Visual Studio 2022 is installed in your system, follow the steps outlined below to create a new .NET Core console application project.

  1. Launch the Visual Studio IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “Console App (.NET Core)” from the list of templates displayed.
  4. Click Next.
  5. In the “Configure your new project” window shown next, specify the name and location for the new project.
  6. Click Next.
  7. In the “Additional information” window, choose “.NET 7.0 (Standard Term Support)” as the Framework version you would like to use.
  8. Click Create.

We’ll use this .NET Core console application project to work with the null object design pattern in the subsequent sections of this article.

What is the null object pattern?

The null object pattern is a behavioral software design pattern that is used to encapsulate the handling of null values in an object-oriented programming language. It is used to help improve code readability and maintainability by eliminating the need for explicit null checks.

The null object pattern defines an abstract class that represents a null value. A concrete subclass is then created that inherits from the abstract class and provides concrete implementations for all of the methods. This concrete subclass is then used throughout the code base whenever a null value needs to be represented.

Why use the null object pattern?

There are a number of reasons to use the null object pattern when working with objects in C#. First, it can help to avoid null reference errors. Second, it can make code more readable by avoiding checks for null values. Third, it can improve performance by avoiding unnecessary calls to methods and properties. Finally, it can make it easier to unit test code.

Implementing the null object pattern in C#

To implement the null object pattern in C#, we’ll follow the three steps outlined below.

  1. Define an interface or an abstract class.
  2. Provide concrete implementations of the methods of the abstract class or the interface in a class that extends either of them.
  3. Define a null implementation by overriding the methods of the abstract base class or the interface and returning appropriate values for your null object.

Create an abstract class in C#

In the console project created earlier, create a class called AbstractProduct, delete the default generated code, and enter the following code.

 <code>
public abstract class AbstractProduct
{
&nbsp;&nbsp;&nbsp; public abstract int Id { get; set; }
&nbsp;&nbsp;&nbsp; public abstract string Name { get; set; }
&nbsp;&nbsp;&nbsp; public abstract string GetProductDetails();
}
</code>

Implement methods of the abstract class in C#

Next, create another new class named Product in a file named Product.cs. Delete the default generated code and enter the following code instead.

 <code>
public class Product : AbstractProduct
{
&nbsp;&nbsp;&nbsp; public override int Id
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; public override string Name
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; public override string GetProductDetails()
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $&quot;Product Id: {Id}, Product Name: {Name}&quot;;
&nbsp;&nbsp;&nbsp; }
}
</code>

Implement a class to handle null values in C#

Create a class named NullProduct to handle null values, delete the default generated code, and enter the following code.

 <code>
public class NullProduct : AbstractProduct
{
&nbsp;&nbsp;&nbsp; public override int Id
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; public override string Name
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; public override string GetProductDetails()
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $&quot;Product Name: {Name}&quot;;
&nbsp;&nbsp;&nbsp; }
}
</code>

Complete our null object pattern example in C#

Finally, we’ll create the ProductRepository class used to work with the product data of our example application. ProductRepository contains a method named GetProduct that accepts the product ID as a parameter and returns either a product instance (if the product is found) or an instance of NullProduct if no product is found.

 <code>
public class ProductRepository
{
&nbsp;&nbsp;&nbsp; List&lt;Product&gt; products = new List&lt;Product&gt;();
&nbsp;&nbsp;&nbsp; NullProduct? NotFound = new() { Id = -1, Name = &quot;Not Available&quot; };
&nbsp;&nbsp;&nbsp; public ProductRepository()
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; products.Add(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Product()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Id = 1,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Name = &quot;DELL Laptop&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; products.Add(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Product()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Id = 2,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Name = &quot;Lenovo Laptop&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; public AbstractProduct GetProduct(int id)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AbstractProduct product = products.Find(x =&gt; x.Id == id);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return product ?? NotFound;
&nbsp;&nbsp;&nbsp; }
}
</code>

Execute the application

Now, use the following piece of code to retrieve a product instance and call the GetProductDetails method to get the details about the product, if one is found.

 <code>
ProductRepository productRepository = new ProductRepository();
var product = productRepository.GetProduct(1);
Console.WriteLine(product.GetProductDetails());
</code>

Figure 1 shows the output.

null object pattern example 01 IDG

Note that, because the product ID (1 in this case) is available in the list of products, the product details (DELL Laptop) are displayed. Now let’s pass a product ID that doesn’t exist as the parameter to the GetProduct method, as shown in the code snippet given below.

 <code>
ProductRepository productRepository = new ProductRepository();
var product = productRepository.GetProduct(3);
Console.WriteLine(product.GetProductDetails());
</code>

This time, the product will not be found and an appropriate message will be displayed at the console window as shown in Figure 2.

null object pattern example 02 IDG

The null object design pattern helps you avoid potential null reference exceptions, simplifies your code, and decreases the amount of clutter that is associated with traditional methods for handling null values. By using a null object in lieu of a null value you can avoid runtime exceptions elegantly, and make your code easier to maintain in the long run.

joydip_kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author