Always will be ready notify the world about expectations as easy as possible: job change page
Jul 11, 2021

Never return NULL references from your functions

Sasha Mathews

In C#, reference types can be assigned null values. This is something that developers will have to live with until they use classes to create software. Unfortunately, the folks at Microsoft cannot simply disallow null assignment to reference variables at compile time, because that would break the codebase of almost every project.

Returning Null is bad practice

What is actually wrong with returning a null reference from the method?

Let’s take a look at this simple method:

public Order GetOrder(int orderId)
    var order = _db.Orders.FirstOrDefault(u => u.OrderId == orderId);
    return order;

The FirstOrDefault method silently returns null if no order is found in the database.

There are a couple of problems here:

  • Callers of GetOrder method must implement null reference checking to avoid getting a NullReferenceException when accessing Order class members. But how is the caller supposed to know how to properly implement error handling? Should the caller throw an exception if it receives a null reference or return some error code?
  • When each caller implements the validation logic on its own, it will be duplicated and the chances are high that the logic will not be consistent across all callers. This is a violation of DRY principle.
  • Getting a nullvalue is an ambiguous for caller, because it doesn’t say whether the null is returned due to the bug or due to the fact that the order was not found in the database. Returning null is definitely not a domain-driven design approach.
  • Returning null is often a violation of the fail fast programming principle. The null can appear due to some issue in the application. The issue can even go to production if the developer has not implemented proper exception handling, which can help quickly detect the issue.

Developers can do several things to improve the situation, such as using a nullable reference types, throwing an exception, or using the null object design pattern.

Use Nullable reference types

If the developer really needs to return a null value from the method (in 99% of cases this is not necessary), the return type can be marked as a nullable reference type (the feature was introduced in C# 8.0).

public Order? GetOrder(int orderId)
    var order = _db.Orders.FirstOrDefault(u => u.OrderId == orderId);
    return order;

Marking a return type as nullable has two main benefits:

  • The method signature clearly states that it can return a null reference. This way, callers know for sure that they need to implement error handling just by looking at the method signature.
  • The compiler will emit a warning if the caller accesses members of the Order class without first checking for a null reference.

Fail fast by throwing an Exception

The fail fast principle is an important principle in software engineering. The idea is pretty simple — as soon as the application detects a problem (null reference), it should throw an exception.

Incorrect orderId can be caused by the following reasons:

  • The auto mapping library is not configured properly to map orderId values.
  • Some code accidentally assigned the wrong value to orderId variable before calling GetOrder method.
  • The frontend does not pass order IDs to the backend.

Each reason described is a bug in the application. Thus, according to the fail fast principle, as soon as the system detects that the orderId is not valid, it should throw an exception.

The easiest way to throw an exception for orders not found is to use the First method instead of FirstOrDefault in the implementation.

public Order GetOrder(int orderId)
    var order = _db.Orders.First(u => u.OrderId == orderId);
    return order;

But we have another problem: callers will get InvalidOperationException without any valuable information because this is a common .NET exception. The solution for that is to introduce a custom exception type which the developer should throw once the order was not found in the database.

public Order GetOrder(int orderId)
    var order = _db.Orders.FirstOrDefault(u => u.OrderId == orderId);
    if (order == null)
        throw new OrderNotFoundException($"Order {orderId} was not found in the database.");
    return order;

To summarize the benefits of the custom exceptions approach:

  • The chances of issues being discovered and fixed prior to deploying a production environment are much higher.
  • The caller will get detailed information about the problem, which will simplify the troubleshooting process.

Use Null object design pattern

Another way to avoid returning null is to use a Null object design pattern.

A null object is an object without behavior like a stub that a developer can return to the caller instead of returning null value.

public Order GetOrder(int orderId)
    var order = _db.Orders.FirstOrDefault(u => u.OrderId == orderId);
    if (order == null)
        return new Order();
    return order;

The caller doesn’t need to check the order for null value because a real but empty Order object is returned.

The null object pattern should be carefully considered as an alternative to throwing an exception. Using the pattern is contrary to the fail fast principle.

This pattern should be used only when callers would otherwise check the object for null in order to skip access to its members.


The conclusion is simple — never return null references from your methods.

Mar 20
Author: Lorenzo Uriel
Nobody likes dealing with a slow query. Besides being stressfull to wait for, it can be a huge impact in your database.Some simpler approaches can help resolve this.I want to start a series of three articles explaining about Tuning and...
Apr 5
Author: Dayanand Thombare
IntroductionCaching is a technique used to store frequently accessed data in a fast-access storage layer to improve application performance and reduce the load on backend systems. By serving data from the cache, we can avoid expensive database queries or API...
Aug 11, 2021
Author: Mel Grubb
Code GenerationCode generation is a great way to apply patterns consistently across a solution or to create multiple similar classes based on some outside input file, or even other classes in the same solution. The tooling has changed over the...
Dec 1, 2023
Author: MESCIUS inc.
Reporting is a common task in business applications, and for that, ComponentOne includes a specialized FlexReport library that allows you to make complex reports. But sometimes, using specialized tools can be too tricky or not flexible enough.For example, if you...
Send message
Your name

© 1999–2024 WebDynamics
1980–... Sergey Drozdov
Area of interests: .NET Framework | .NET Core | C# | ASP.NET | Windows Forms | WPF | HTML5 | CSS3 | jQuery | AJAX | Angular | React | MS SQL Server | Transact-SQL | ADO.NET | Entity Framework | IIS | OOP | OOA | OOD | WCF | WPF | MSMQ | MVC | MVP | MVVM | Design Patterns | Enterprise Architecture | Scrum | Kanban