Introduction

There was a tweet from David Fowler the other day about the different ways in which you can do essentially the same thing in modern C# and it got me thinking.

Which do I like and why? Is one better than the other? Is it all subjective?

The Classic

Let’s start off by looking at the classic null check which has been in C# since the beginning of the language.

var thing = Thing.Get(id);
if (thing != null)
{
    thing.Do();
}

Pros: It’s clear. It’s familiar. It’s been in the language since the beginning. Cons: It’s verbose. People will argue it’s not intuitive to people starting their developer journey. What is null?

Checking it’s an Object

var thing = Thing.Get(id);
if (thing is object)
{
    thing.Do();
}

Pros: Removes the magical null check. Cons: Not backwards compatible as is object is relatively new concept. Need to understand what object is now and how it relates.

Constant Pattern Matching

var thing = Thing.Get(id);
if (thing is not null)
{
    thing.Do();
}

Pros: Clear English language being explicit what’s going on. Cons: Back to needing to know about null but also combination of is and not. It’s also not backwards compatibly as relatively new concept in the language. I can see this one catching on though.

Further reading - https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#constant-pattern

Pattern Matching

var thing = Thing.Get(id);
if (thing is { } t0)
{
    t0.Do();
}

Pros: Personally not sure there are any positives for this construct. Pattern matching to this syntax for this use case seems clunky. Cons: High cognitive load to a mentally parse what is going on. Using pattern matching to check if it’s an object doesn’t feel right. Has an additional variable t0 to use.

Is a Thing

var thing = Thing.Get(id);
if (thing is Thing t1)
{
    t1.Do();
}

Pros: I quite like this pattern. It doesn’t really make sense in this scenario personally so might be classed as a con. I like this pattern match if there is inheritance going on and you want to check for a specific derived type. Cons: Like I said before in this scenario it feels like overkill (although no benchmarks to back this up) just to check to see if thing is null or not.

Further reading - https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#declaration-and-type-patterns

Null Conditional

var thing = Thing.Get(id);
thing?.Do();

Pros: Clean with no nesting. Will only execute Do() if thing is not null. Cons: Like a lot of the above it comes down to style, some developers do not like this syntax.

Further reading - https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators--and-

Conclusion

Like everything I think it comes down to “it depends”. It depends on age of code base. It depends on internal coding standards. It depends on consistency of usage. It depends on target framework and language version being used. It depends on personal preference. There are a number of options above I do not like and some that I use nearly on a daily basis.

What are you thoughts? Reach out on twitter @WestDiscGolf and let me know!