C#11 Parameter Null Checking

Such is life on Twitter, I’ve been watching from afar .NET developers argue about a particular upcoming C# 11 feature, Parameter Null Checks. It’s actually just a bit of syntactic sugar to make it easier to throw argument null exceptions, but it’s caused a bit of a stir for two main reasons.

  1. People don’t like the syntax full stop. Which I understand, but other features such as some of the switch statement pattern matching and tuples look far worse! So in for a penny in for a pound!
  2. It somewhat clashes with another recent C# feature of Nullable Reference Types (We’ll talk more about this later).

The Problem

First let’s look at the problem this is trying to solve.

I may have a very simple method that takes a list of strings (As an example, but it could be any nullable type). I may want to ensure that whatever the method is given is not null. So we would typically write something like :

void MyMethod(List<string> input)
{
    if(input == null)
    {
        throw new ArgumentNullException(nameof(input));
    }
}

Nothing too amazing here. If the list is null, throw an ArgumentNullException!

In .NET 6 (Specifically .NET 6, not a specific version of C#), a short hand was added to save a few lines. So we could now do :

void MyMethod(List input)
{
    ArgumentNullException.ThrowIfNull(input);
}

There is no magic here. It’s just doing the same thing we did before with the null check, but wrapping it all up into a nice helper.

So what’s the problem? Well.. There isn’t one really. The only real issue is that should you have a method with many parameters, and all of them nullable, and yet you want to throw a ArgumentNullException, you might have an additional few lines at the start of your method. I guess that’s a problem to be solved, but it isn’t too much of a biggie.

Parameter Null Checking In C# 11

I put C# 11 here, but actually you can turn on this feature in C# 10 by adding the following to your csproj file :

<EnablePreviewFeatures>True</EnablePreviewFeatures>

Now we have a bit of sugar around null check by doing the following :

void MyMethod(List<string> input!!)
{
}

Adding the “!!” operator to a parameter name immediately adds an argument null check to it, skipping the need for the first few lines to be boilerplate null checks.

Just my personal opinion, it’s not… that bad. I think people see the use of symbols, such as ? or ! and they immediately get turned off. When using a symbol like this, especially one that isn’t universal across different languages (such as a ternary ?), it’s not immediately clear what it does. I’ve even seen some suggest just adding another keyword such as :

void MyMethod(notnull List<string> input)
{
}

I don’t think this is really any better to be honest.

Overall, it’s likely to see a little bit of use. But the interesting context of some of the arguments against this is….

Nullable Reference Types

For why I am totally wrong in all of the below, check this great comment from David. It explains why, while the below is true, it’s also not the full story and I am wrong in suggesting that you only need one or the other!

C#8 introduced the concept of Nullable Reference Types. Before this, all reference types were nullable by default, and so the above checks were essentially required. C#8 came along and gave a flag to say, if I want something to be nullable, I’ll let you know, otherwise treat everything as non nullable. You can read more about the feature here : https://dotnetcoretutorials.com/2018/12/19/nullable-reference-types-in-c-8/

The interesting point here is that if I switch this flag on (And from .NET 6, it’s switched on by default in new projects), then there is no need for ArgumentNullExceptions because either the parameter is not null by default, or I specify that it can be null (And therefore won’t need the check). submit press release to crypto media press release today and free

Just as an example, with Nullables switched on using code :

#nullable enable
void MyMethod(List<string> input)
{
    //Input cannot be null anyway. So no need for the check. 
}


void MyMethod2(List<string>? input)
{
    //Using ? I've specified it can be null, and if I'm saying it can be null...
    //I won't be throwing exceptions when it is null right? 
}

There’s arguments that nullable reference types are a compile time check whereas throwing an exception is a runtime check. But the reality is they actually solve the same problem just in different ways, and if there is a push to do things one way (nullable reference types), then there’s no need for the other.

With all of that being said. Honestly, it’s a nice feature and I’m really not that fussed over it. The extent of my thinking is that it’s a handy little helper. That’s all.

2 thoughts on “C#11 Parameter Null Checking”

  1. At the end you talk about Nullable Reference Types and make the statement “then there is no need for ArgumentNullExceptions because either the parameter is not null by default, or I specify that it can be null (And therefore won’t need the check).”

    This is a bad statement to make. For example, in your example of:
    #nullable enable
    void MyMethod(List input) {}

    ^ I can call that method as such: MyMethod(null!); // this will suppress the compiler warning and null reference exception will happen.

    Additionally, if your method is a public API and the consumer of your API doesn’t have nullable turned on, it can pass in null all day long without a warning – and even if they do have nullable enabled, they can still pass in “null!” to get around the compiler warning.

    Last, and certainly not least, the nullable detection logic at compile time is not perfect. This means that even though the compiler thinks something is not null, at run time, due to unpredicted circumstances, the variable / value passed in might be null, and because you don’t have null checking because you have nullable turned on, the software will blow up.

    In my opinion, the nullable reference type feature added in C# is a bad feature cause it lures people into a false sense of security because they assume null can’t be passed into their functions, but nullable reference types don’t prevent that at all.

    Reply

Leave a Comment