Wednesday, April 20, 2022

C# 11.0: Parameter Null Checking (Revisited)

C# 11.0 was initially planned to have the bang-bang operator for improved Parameter Null Checking. If you don't know what that is, I have written this post a while back.
   C# 11.0 Preview: Parameter Null Checking

But unfortunately, the C# Lang team has deferred this feature and we won't be having this feature in C# 11.0. 

With C# 10.0 and .NET 6, we still have the ArgumentNullException.ThrowIfNull method which is the recommended/preferred approach for going forward. So while we are here, maybe it's worth having a closer look at ArgumentNullException.ThrowIfNull.

Basically, with this feature syntax is something like below.
static void PrintFullName(Person person)
{
    ArgumentNullException.ThrowIfNull(person);
 
    Console.WriteLine($"FullName: {person.FirstName} {person.LastName}");
}
Now If I call this method supplying a null value, I am going to get an exception something like below.
Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'person')
   at System.ArgumentNullException.Throw(String paramName)
   at System.ArgumentNullException.ThrowIfNull(Object argument, String paramName)
   at Program.<<Main>$>g__PrintFullName|0_0(Person person) in C:\Users\Jaliya\Desktop\ConsoleApp1\ConsoleApp1\Program.cs:line 3
   at Program.<Main>$(String[] args) in C:\Users\Jaliya\Desktop\ConsoleApp1\ConsoleApp1\Program.cs:line 8

So here in the exception, we have the following details.

And these Caller Info attributes were introduced in C# 5.0 back in 2012.

If you notice the exception, you should see we also have the name of the parameter in the exception. But when doing ArgumentNullException.ThrowIfNull, we haven't included the parameter name. So what happened here?

Enter CallerArgumentExpressionAttribute.

This new attribute was introduced with C# 10.0, and this allows us to capture the expressions passed to a method. If you examine the ArgumentNullException.ThrowIfNull method, you will see it's using this new attribute as below and that's how we are getting parameter name in the exception.

public static void ThrowIfNull([NotNull] objectargument, [CallerArgumentExpression("argument")] stringparamName = null);

Reference: ArgumentNullException.cs

Let's consider the below code.

static void PrintFullName(Person person)
{
    ThrowIfNull(person);
}
 
static void ThrowIfNull(object argument, [CallerArgumentExpression("argument")] stringexpression = default)
{
    if (argument is null)
    {
        throw new ArgumentNullException(expression);
    }
 
    Console.WriteLine($"Expression: {expression}");
}

Now if I call these methods as follows, I am getting these outputs.

PrintFullName(new Person("John""Doe"));
// Expression: person
ThrowIfNull(new Person("John""Doe")); // Expression: new Person("John", "Doe")
PrintFullName(null);
// System.ArgumentNullException: Value cannot be null. (Parameter 'person')
ThrowIfNull(null);
// System.ArgumentNullException: Value cannot be null. (Parameter 'null')

Hope this helps.

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment