UPDATE (9/23/2021): This feature, unfortunately, did not make it into C# 10. This post was written before the feature set for C# 10 was finalized. I'm leaving it up, but know that the demo in this post won't work in C# 10. You can track the corresponding feature request on GitHub.

Let's continue our Bite-Size C# 10 series with a cool new way to simplify methods with nullable parameters: null parameter checking.

Current Implementation

C# 9.0 and earlier provides no native way to check if reference types, such as string, have the value null when being passed into a method.

Often, that means we have to do some form of null-checking right at the beginning of these kinds of methods:

public string FormatName(string name)
{
    if(name == null)
        return "Error";
    //...Rest of implementation
}

public void FormatCustomClass(MyCustomClass customClass)
{
    if(customClass == null)
        return;
    //...Rest of implementation
}

New Implementation

In C# 10, we will be allowed to use the ! operator to tell the compiler to check for null values in parameters to a method, which eliminates the null checks:

public string FormatName(string name!)
{
    //...Rest of implementation
}

public void FormatCustomClass(MyCustomClass customClass!)
{
    //...Rest of implementation
}

The program will then throw ArgumentNullExceptions if any of the marked parameters are null on method invocation.

Other Considerations

The specification for this feature mentions the following problem: what happens if a nullable object uses this null-check operator?

public void FormatDate(DateTime? date!)
{
    //...Rest of implementation
}

In this situation, the specification says that a warning will be thrown by the compiler. But why not an error?

The above seems like a nonsensical piece of code, but the specification mentions the following structure that could potentially force developers into a situation like this:

// Assembly1
abstract class C1 {
    protected abstract void M(object o); 
}

// Assembly2
abstract class C2 : C1 {
   protected override void M(object? o) { 
       //...
   }
}

// Assembly3
abstract class C3 : C2 { 
    protected override void M(object o!) {
        //...
    }
}

Note the override void M(object? o) method in class C2. Having a class with that signature will cause the author of Assembly3 to get an error (because class C3 inherits from class C2), and be forced to change their method to this:

// Assembly3
abstract class C3 : C2 { 
    protected override void M(object? o!) {
        ...
    }
}

At this point, the author of Assembly3 will get the aforementioned warning, and can either ignore it, suppress it, or refactor the method.

Demo Project

As with other items in this series, the example for null parameter checking in the demo project won't compile, since this feature is not yet included in the C# 10 preview. I included a sample of how it might work anyway:

GitHub - exceptionnotfound/CSharp10Features
Contribute to exceptionnotfound/CSharp10Features development by creating an account on GitHub.

Happy Coding!