Why does the null-conditional operator behave differently for == and .Equals()?

853 Views Asked by At

I had the following code, which works fine:

var firstChild = token.First as JProperty;
bool isHref = token.Children().Count() == 1
           && firstChild?.Name == "href";

I wanted to make the string comparison case-insensitive, so I changed it to:

var firstChild = token.First as JProperty;

bool isHref = token.Children().Count() == 1
           && firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase);

Now the compiler is giving me an error:

Operator && cannot be applied to operands of type 'bool' and 'bool?'

I can fix the error by coalescing to false like

bool isHref = token.Children().Count() == 1
         && (firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase) ?? false);

But I'm curious why the compiler doesn't like the first null-conditional syntax.

2

There are 2 best solutions below

1
On BEST ANSWER

Let's simplify to the essentials.

string x = null, y = null;

// this is null.  b1 is bool?
var b1 = x?.Equals(y); 

// b2 is bool
// this is true, since the operator doesn't require non-null operands
var b2 = x == y;

Basically .Equals() requires a non-null object to operate on. That's different than ==, which is statically bound, not dynamically dispatched.

2
On

the first expression returns null or bool

if firstChild is null then the return value will be null and it can not be used in an if condition

firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase)

will the same as

firstChild == null ? null : firstChild.Name.Equals("href", StringComparison.OrdinalIgnoreCase)