I'm sure you've met the C# coalesce operator, where you can use a double question mark to check for null:
x = y ?? z;
... being equivalent to:
<span style="color: #0000ff">if</span> (y != <span style="color: #0000ff">null</span>)
x = y;
<span style="color: #0000ff">else</span>
x = z;
It's a handy shortcut, but sometimes it doesn't behave quite as
you
I might expect.
Here's an example:
I wanted to combine the elements of an address to make a field that was searchable with a SQL LIKE statement. As we use LINQ to SQL, I needed an expression that LINQ to SQL could translate into SQL syntax. I wrote this:
...
select <span style="color: #0000ff">new</span>
{
SearchableAddress = c.Address.HouseName ?? "<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>"
+ c.Address.HouseNumber ?? "<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>"
+ c.Address.Road ?? "<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>"
+ c.Address.Town ?? "<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>"
+ c.Address.County ?? "<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>"
+ c.Address.Postcode ?? "<span style="color: #8b0000"></span>"
}
I'm using the coalesce operator to replace nulls with empty strings - otherwise SQL returns NULL for the whole expression if a single element is NULL.
However, I found my search was rarely getting any matches, and a little digging isolated the above expression as the culprit.
It turns out that the coalesce operator takes lower precedence than the concatenation operator. What I meant (and what I should have written) was this:
...
select <span style="color: #0000ff">new</span>
{
SearchableAddress = (c.Address.HouseName ?? "<span style="color: #8b0000"></span>") + "<span style="color: #8b0000"> </span>"
+ (c.Address.HouseNumber ?? "<span style="color: #8b0000"></span>") + "<span style="color: #8b0000"> </span>"
+ (c.Address.Road ?? "<span style="color: #8b0000"></span>") + "<span style="color: #8b0000"> </span>"
+ (c.Address.Town ?? "<span style="color: #8b0000"></span>") + "<span style="color: #8b0000"> </span>"
+ (c.Address.County ?? "<span style="color: #8b0000"></span>") + "<span style="color: #8b0000"> </span>"
+ (c.Address.Postcode ?? "<span style="color: #8b0000"></span>")
}
... but my version without any parentheses was equivalent to this:
...
select <span style="color: #0000ff">new</span>
{
SearchableAddress = c.Address.HouseName ??
("<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>" + c.Address.HouseNumber) ??
("<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>" + c.Address.Road) ??
("<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>" + c.Address.Town) ??
("<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>" + c.Address.County) ??
("<span style="color: #8b0000"></span>" + "<span style="color: #8b0000"> </span>" + c.Address.Postcode) ??
"<span style="color: #8b0000"></span>"
}
Getting back the first non-null element, padded with a superfluous space, was enough to make the search work occasionally enough to be confusing.
Maybe I should have seen it coming, as I'd happily use:
a = b ?? c ?? d ?? e;
to get the first non-null value, but that string concatenation threw me off the scent.
I dunno - to me coalesce feels like a unary operator, so I'd expect it to be evaluated first; it turns out it gets evaluated almost last. What do you think?