Is It Worth to Check for Null All the Time?


Null checking refers to ensuring that no code passes the null reference to a method.

Developers use it to ignore invalid objects or handle exceptions that might occur due to nulls. It is supposedly good to check for nulls. So, the question is, “Should you check for null if you do not even expect null?”

In this article, you will find the answers to all your questions regarding null checking. So, let’s get started!

Do you need to check for null even if you don’t expect null?

Checking for nulls is a good habit, as you can avoid running into an unexpected result or error. However, if you keep checking for nulls everywhere in your application, you may end up with unnecessarily complicated code that is less readable and testable.

Let’s take a look at the following code example.

Assume that we have a Car class with three member variables, i.e., _name, _model, and _color.

You need to keep in mind that strings can be null. We declare the string variables at the beginning of the class.

In the following code, we have a constructor that initializes the car object after checking the argument values. So, you can see how checking for the nulls can make the code complex and difficult to read.

class Car
{
    //string instance variables       
    private string _name;
    private string _model;
    private string _color;


    //Constructor to initialize the object
    public Car(string name, string model, string color)
    {
        //Checking name for null
        if (name != null)
        {
            //Checking model for null
            if (model != null)
            {
                //Checking color for null
                if (color != null)
                {
                    //initializing object if values are not null
                    _name = name;
                    _model = model;
                    _color = color;
                    Console.WriteLine("Car Created Successfully!");
                }
            }
        }
        else
        {
            Console.WriteLine("Null Car Created!");
            //or throw exception
        }
    }
}

Now, you may ask if someone really writes the code as above.

Yes!

They do.

Many programmers check for the nulls even if they do not need to. However, whether you check for nulls or not depends entirely upon the situation. Generally, you should check for nulls and method parameters when the method is called from outside the application scope.

For example, suppose you will create the Car class instance (the above example) somewhere outside the application and doubt that the caller may pass the nulls as references. If the null occurs, then handle it accordingly:

//Checking name for null
if (name != null)
{
    //Checking model for null
    if (model != null)
    {
        //Checking color for null
        if (color != null)
        {
            var car = new Car(name, model, color);
        }
    }
}
else
{
    //some code here
}

In contrast, you should do less null checking in the code internal to the application, e.g., the code in the service classes and domain classes. For example, if you know for sure that the caller will or cannot pass nulls, you can skip the null checks.

How to Handle Nulls Passed to Parameters?

After performing a null check, you need to handle the nulls if passed to parameters. There are various approaches to handling nulls in C#, such as:

  • Raising the NullReferenceException,
  • Throwing custom exceptions,
  • Recover via default values.

Let’s discuss each approach in detail.

Raising NullReferenceException

Ah, the good old NullReferenceException. One of the main causes of spending hours debugging the code.

The compiler throws the NullReferenceException when a function cannot accept the null parameters, or when you attempt to call a property or a method on an object that is not initialized.

But you can check for the nulls and throw NullReferenceException in your code as well.

class Car
{
    private string _name;
    private string _model;
    private string _color;

    public Car(string name, string model, string color)
    {
        _name = name;
        _model = model;
        _color = color;
    }

    public void PrintCar()
    {
        //Checking name for null
        if (_name != null && _model != null && _color != null)
        {

            Console.WriteLine($"Name: {_name}\nModel: {_model}\nColor: {_color}");
        }
        else
        {
            throw new NullReferenceException(); //throwing exception 
        }
    }
}

Then you need to have in mind to handle it in the calling code.

//passing nulls to the constructor
Car car = new Car(null, null, null);

//Handling NullReferenceException
try
{
    car.PrintCar();
}
catch(NullReferenceException)
{
    Console.WriteLine("Invalid data! \n");
}
Console.ReadKey();

When you execute the above code, you will see that your program runs successfully. However, it displays a message on the screen showing the null occurrence.

Throw Custom Exceptions

If you want to handle nulls in your way, you can create a custom exception

//creating a custom exception 
class InvalidNameException : Exception
{
    public InvalidNameException() : base()
    {
    }

    public InvalidNameException(String message) : base(message)
    {
    }

    public InvalidNameException(string? message,
                                Exception? innerException) : base(message,
                                                                    innerException)
    {
    }
}

and throw them whenever a null is passed to parameters, as shown in the following example:

public static void WriteUserName(string name)
{
    //Checking if name is null
    if (name != null)
    {
        Console.Write("Name: " + name);
    }
    else
    {
        //throwing custom exception 
        throw new InvalidNameException("Name cannot be null"); 
    }
}

Try to recover through default values

You can simply initialize an object by assigning it a default value whenever it is set to null as follows:

public static void WriteUserNameOrUseDefaultValue(string name)
{
    //Checking if name is null and
    //assigning a default value if yes
    if (name == null)
    {
        name = "John";
    }
    Console.Write("Name: " + name);
}

Now that you have seen how to handle the nulls if passed for parameters let’s focus on how to avoid them as much as possible.

Avoid using null as much as possible

Avoiding nulls is better than handling them. If your code returns or passes the nulls irrespective of their need, you must refactor it and avoid nulls wherever possible. Here are the three ways to minimize the nulls in C#:

  1. With C# Nullable Reference types – C# 8 introduced the Nullable Reference Types to minimize the chance of NullReferenceExceptions. They have useful features that help developers avoid returning nulls, such as the ability to see if a variable is null before dereferencing it, using variable annotations to declare variables as null explicitly, and many more.
  1. With the NullObject pattern, eliminate returning null values – The NullObject pattern implies that you define a class that implements ‘do nothing’ behavior and use its instance wherever you need to check for nulls or return the null to avoid raising NullReferenceException.
  1. Return Result type instead of null – By returning Result types in methods, you can avoid returning nulls or raising NullReferenceException very easily. Many programming languages allow this, and C# has many libraries to do so.

By adopting any of the approaches above, you can get rid of many problems that you face due to nulls. However, if you want to learn more about these ways and how to implement them, please read a separate article on whether to return a null or empty value from a method. It describes the above suggestion in detail.

Conclusion

Many programmers stay confused about whether to check for nulls or not, especially when they least expect them. It is a hot topic.

Some people support the idea that you should check for nulls regardless of their possibility of occurring. However, from the discussion above, you can conclude that null checking is just overhead on the compiler and does not serve any purpose when done unnecessarily.

Therefore, the recommendation is to avoid using and handling nulls and return empty values to keep your code clean, readable, and organized.

Recent Posts