0 Comments

Null conditional operator allows us to write more terse code. And unfortunately, more subtle bugs. The combination of Null Conditional Operator with Any() is easily my current favourite for The Winner of 2019’s Most Bugs Caused by a New C# Feature.

Combining Null Conditional Operator ?. with System.Linq.Enumerable.Any allows us to quickly check if our collection is not null AND not empty. So instead of writing this:

        public static void DoWork(List myWorkItems)
        {
            if (myWorkItems != null && myWorkItems.Any())
            {
                Console.WriteLine("Doing work");
                return;
            }

            Console.WriteLine("Nothing to do");
        }

We can use Null Conditional Operator and save few key strokes:

        public static void DoWork(List myWorkItems)
        {
            if (myWorkItems?.Any() == true)
            {
                Console.WriteLine("Doing work");
                return;
            }

            Console.WriteLine("Nothing to do");
        }

Maybe we could make the code even better, by reducing nesting by inverting the if:

        public static void DoWork(List myWorkItems)
        {
            if (myWorkItems?.Any() == false)
            {
                Console.WriteLine("Nothing to do");
                return;
            }

            Console.WriteLine("Doing work");
        }

Ah, no. Did you spot the bug?

image

If we expand the example, we get a better picture of the situation:

image

Why this happens? Because myWorkItems?.Any() doesn’t return false when the collection is null. It returns Nullable Boolean instead:

image

Getting around the issue is quite simple: Instead of checking for == false, we check for != true:

            if (myWorkItems?.Any() != true)
            {
                Console.WriteLine("Nothing to do");
                return;
            }

But do we always remember this? Based on the code I’ve seen this year the answer is quite simply no.

Maybe there’s a Roslyn Analyzer for spotting this automatically?