Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Safe navigation operator - what is actually going on?

Tags:

I've been following the safe navigation operator feature added in C#6 with some interest. I've been looking forward to it for a while. But I'm finding some different behavior than I expected. I'm realizing I really don't understand how it actually works.

Given this class

class Foo {
    public int? Measure;
}

Here's some code using the new operator.

Foo f = new Foo { Measure = 3 };
Console.WriteLine(f?.Measure);  // 3

f = new Foo { Measure = null };
Console.WriteLine(f?.Measure);  // null

f = null;
Console.WriteLine(f?.Measure);  // null

Up to here, everything's working as expected. ?. is accessing members when the left hand side is not null, otherwise returning null. But here things go in a direction I wasn't expecting.

var i = f?.Measure; // i is Nullable<int>
Console.WriteLine(i.HasValue); // false
Console.WriteLine(f?.Measure.HasValue); // null

What?

Why can I get HasValue from i, but not from the same expression I assigned to i? How can HasValue ever be null?

Edit: My real question is about program behavior, not a compilation error. I removed the extra stuff about compilation, and focused this question more narrowly on why two different results are returned by what seems like the same logic.

like image 888
recursive Avatar asked Aug 28 '15 01:08

recursive


1 Answers

Let's walk through this logically.

var f = ???;
var i = f?.Measure;
var t = i.HasValue;

We don't know if f is null or not.

  1. If f is null, then the result (i) is null
  2. If f is not null, then the result (i) is an int

Therefore, i is defined as int?, and t is a bool

Now, let's walk through this:

var f = ???;
var i = f?.Measure.HasValue;
  1. If f is null, then the result (i) is null
  2. If f is not null, then the result (i) is Measure.HasValue, which is a bool.

Therefore, i is a bool?.

If f is null, we short-circuit and return null. If it's not, we return the bool result of .HasValue.

Essentially, when using ?. - the return type must be a reference value, or a Nullable<T>, as the expression can short circuit to return null.

like image 167
Rob Avatar answered Nov 12 '22 21:11

Rob