måndag 10 december 2018

Overuse Example of the Null Coalescing Operator (??) and Null-Conditional Operator (?.)

The sweet taste of syntactic sugar

From Wikipedia
In computer science, syntactic sugar is syntax within a programming language that is designed to make things easier to read or to express. It makes the language "sweeter" for human use: things can be expressed more clearly, more concisely, or in an alternative style that some may prefer.

Sometimes though, too much of the sweetness can become a mouthful.

Suppose you need this to guard against collections that are null or empty



but in the rush you head directly for the sweet style. Its shorter and doesn't repeat the variable name, but is it really more readable?


Last week I saw code like that. Since my own code was dependant on that method I really would like it to be correct. At a first glance it appeared to be buggy. So I tried it out in LinqPad and saw that it behaved totally correct and therefore felt a bit perplexed. Do you?

There's three cases
  1. collectionOfInts has at least one value
  2. collectionOfInts is empty
  3. collectionOfInts is null
I find the first and second case pretty straightforward, but I couldn't evaluate the null scenario in my head. For instance, I became unsure about the operator precedence between "!" and "??".

Unfolding

It was when I started to dissect the code it became apparent what it was that confused me.

I expanded
collectionOfInts?.Any() 

to
collectionOfInts == null ? null : collectionOfInts.Any()

and saw that I had a type conversion error. I had to cast null to a type.
collectionOfInts == null ? (bool?)null : collectionOfInts.Any()

Up until now I hadn't realized that the result from the "?."-operator was a nullable bool. Reading up on operator precedence I learned that the "!"-operator has much higher precedence than the "??". Those are two clues to what goes on here.

What type and value do you think the variable "result" will get in the code below?


As shown below, "result" is a nullable bool that is null! Not null is null!



This means that when collectionOfInts is null the code can be rewritten like this:
!collectionOfInts?.Any() ?? true 
!(bool?)null ?? true
(bool?)null ?? true
true


So, no sugar in this case?

After having discussed the code with the author and realizing that he also had trouble understanding what happens in the null case, I say "no"! The sugar is there to make the code more readable, but apparantly it doesn't in this case.

Make your own sugar

There is a solution though, that I find easiest to read, but was a bit surprising when I first saw it, and that is:
if (collectionOfInts.IsNullOrEmpty())

The thing that surprised me was that the author believed that you could call a method on an object that is null. But you kind of can. If the method is an extension method.

If you make an extension method like the one below it also works for strings, since a string implements IEnumerable<char>


Is it worth using the extension method and risking surprising a reader of the code?
People seem to disagree about that :)

https://stackoverflow.com/questions/790810/is-extending-string-class-with-isnullorempty-confusing
https://stackoverflow.com/questions/14196593/why-is-mystring-isnullorempty-not-built-into-net
https://stackoverflow.com/questions/8582344/does-c-sharp-have-isnullorempty-for-list-ienumerable