Yo, Yo, Check Null
Tags: csharp, discuss
Published: 2020-06-20 11:58:56

It is a very common practice to check for null in parameters:

```csharp
public void DoSomething(Foo foo)
{
    if (foo is null)
    {
        throw new ArgumentNullException(nameof(foo));
    }
}
```

In this blog, I want to talk about parameter null validation: why, when, and how.


## Why

It's suggested in many coding style rules, it's followed in many open source projects, but why? What would happen if we don't check whether the parameter is null? What's the benefit of it?

Let's take a look at the following example:

```csharp
public void PrintCar(Car car)
{
    if (car is null)
    {
        throw new ArgumentNullException(nameof(foo));
    }
    Console.WriteLine(car.Name);
}
```

In this case, if we don't check whether the parameter is null, it will raise `NullReferenceException`; if we check, it will raise `ArgumentNullException`. It looks like the `NullReferenceException` is gone, but actually we get a new `ArgumentNullException`. The caller still has to handle it. The number of exceptions doesn't change at all. 

Referring to Voldemort as 'You-Know-Who' cannot kill him.

If a method catches an exception and doesn't has the ability to handle it, is it needed to check the null parameters? 

Different people have different opinions.

In the blog [<Why I Never Null-Check Parameters>](https://dzone.com/articles/why-i-never-null-check-parameters), the author made a point that it doesn't make sense if you catch the exception and ignore it. 

In my opinion, parameters null validation is necessary and useful in most cases.

The first reason is that, `NullReferenceException` is different from `ArgumentNullException`. The name of exceptions can help us find the responsible party. If you call the method and you get a `ArgumentNullException`, you may figure out there is something wrong with the parameters. Just like 40x and 50x status code in HTTP. `Bad Request` is totally different from `Server Error`.

The second reason is that, most methods are not stateless. In these stateful methods, an exception in the middle of the method will mess the states up and we cannot roll back easily.

Take a look at this example:

```csharp
public void CarCounter(Car car)
{
    // #1
    this.CarCount += 1;
    // #2
    this.CarNames.Add(car.Name);
}
```

When car is null, it will raise an exception in line #2. However, there is a state update in line #1. This may modify the count incorrectly. We need a mechanism like transaction in DB to roll back the executed part of the method. It may be very complicated. And for some cases like notification, the actions are irrevocable.

As a conclusion, in most cases parameter null validation is necessary and useful. It can avoid the execution which shouldn't happen, and it can specify the responsibility of the unexpected exception.

## When

As we talked above, it's meaningful to check the null parameters. But should we check all method parameters in our projects?

It depends.

For public method, we don't know what parameters the caller will pass,  we should check null parameters before the business logic.

For private methods, we needn't check because we are supposed to know how and where this method is called. In this situation, the null variables should be checked outside of the method before calling it.

It's a good choice to enable the [CA1062](https://docs.microsoft.com/en-us/visualstudio/code-quality/ca1062?view=vs-2019) Warning. With this warning, we needn't care about when to validate the parameters. Just think about which access modifier should be used, public or private.


## How

The following question is, how to check null parameters. The code for validation is verbose and useless. Validating null parameters everywhere will make the code less human-readable.

In the blog [<C# Futures: Simplified Parameter Null Validation>](https://www.infoq.com/news/2020/01/CSharp-Null-Validation/), the author went through many ways to validate the parameters. The [C# Proposal #2145](https://github.com/dotnet/csharplang/issues/2145) about bang operator is very interesting and I am really looking forward to it.

Given Code Contract is [deprecated](https://github.com/microsoft/CodeContracts/issues/409#issuecomment-216083336), wrapping the validation into a Helper is a better choice:

```csharp
internal static class ThrowIf
{
    public static class Argument
    {
        public static void IsNull<T>(T argument, string name)
        {
            if (argument is null)
            {
                throw new ArgumentNullException(name);
            }
        }
    }
}
public void DoSomething(Foo foo)
{
    ThrowIf.Argument.IsNull(foo, nameof(foo));
}
```

Please let me know if you have another solution. Thanks.


***

References:
- [Avoid Check for Null Statement in Java](https://www.baeldung.com/java-avoid-null-check)
- [Why I Never Null-Check Parameters](https://dzone.com/articles/why-i-never-null-check-parameters)
- [Implementing an Exception Helper Class for Parameter Null Checking](https://mariusschulz.com/blog/implementing-an-exception-helper-class-for-parameter-null-checking)
- [Code Contracts | MS Docs](https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts)
- [Code Contracts | MS Reserch](https://www.microsoft.com/en-us/research/project/code-contracts/)
- [Elegant method parameter validation with Code Contracts support](https://blog.rsuter.com/elegant-method-parameter-validation-with-code-contracts-support/)
- [Do you throw an argumentexception or argumentnullexception from private methods?](https://softwareengineering.stackexchange.com/questions/100214/do-you-throw-an-argumentexception-or-argumentnullexception-from-private-methods)
- [Should I throw on null parameters in private/internal methods?](https://stackoverflow.com/questions/34834033/should-i-throw-on-null-parameters-in-private-internal-methods)
- [C# 9 Null](https://www.infoq.com/news/2020/06/CSharp-9-Null/)

***

Update:
Thanks to [Sam](https://dev.to/sam_ferree/comment/10j90) for suggesting replace `== null` with `is null` because the == operator can be overloaded.

Update2:
Thanks to [sunilmusinada](https://dev.to/sunilmusinada/comment/10ka1) for suggesting replace hardcode param type with nameof.

Update3:
Thanks to [Zohar](https://dev.to/peledzohar/comment/10ofk) for pointing out the mistake I made that I put the parameter's type name in exception instead of the parameter's name