C# 9.0 Null Checking

C# 9.0 Null Checking

data codes through eyeglasses

C# 9.0 added a lot of new features and enhanced others. Here we’re covering Pattern Matching, more specifically is null and is not null.  Beginning with C# 7.0, the “is” operator was added to match an expression against a pattern, and with C# 9.0 the negation pattern was added to do a non-null check.

Overview

So why not just use “==” or “!=” operators?

When you override the operators, your traditional null checks can behave differently. This is why it can be safer for you to use the newer pattern matching.

The addition of null checking using, “is null“, though similar to, “!= null“, is not the same. Syntactically, it is similar to SQL though its meaning is much different.

Evolution of Null Checking

C# 7

The ‘is’ keyword was introduced in C# 7. Below are some sample usages.

// Old method
public bool IsValid(string userName)
{
  if (userName == null)
    throw new ArgumentNullException(nameof(userName));

  return userName.Length > 6;
}

// C# 7 - is keyword
public bool IsValid(string userName)
{
  if (userNameis null)
    throw new ArgumentNullException(nameof(userName));

  return userName.Length > 6;
}

// C# 7 - '??' null-coalescing operator and '_' discard example
public bool IsValid(string userName)
{
  _ = name ?? throw new ArgumentNullException(nameof(userName));

  return userName.Length > 6;
}

C# 9

As stated earlier, C# 9 introduced the combination of ‘is’ and ‘not’ to provide a complete logical pattern; similar to that found in SQL.

// C# 9 - 'is not null' logical pattern
if (userName is not null)
  userName.Length > 6;
else
  throw new ArgumentNullException(nameof(userName));

Prior to this, developers would have to write it as follow. This is a bit messy when it comes to proper patterns and practices; let alone code reviews.

// Old method
if (!(userName is null))
  userName.Length > 6;
else
  throw new ArgumentNullException(nameof(userName));

Full Example

As stated earlier, some developers override the ‘==’ and ‘!=’ operators. So, let’s dig into that. You can execute the sample using your favorite IDE or RoslynPad.

Note, that we’re overriding the stark contrast in outputs.

public class User
{
  public static bool operator ==(User userA, User userB)
  {
    return false;
  }

  public static bool operator !=(User userA, User userB)
  {
    return false;
  }

  public override bool Equals(object? obj)
  {
    return base.Equals(obj);
  }
}

User me;
User you = new User();

Console.WriteLine($"me == null   {me == null}");
Console.WriteLine($"me is null   {me is null}");
Console.WriteLine($"me == you    {me == you}");

// OUTPUT:
// me == null   False
// me is null   True
// me == you    False

Further Reading

If you’d like other helpful tips, check out Thomas Claudishuber’s blog.