Can the property be null ever or is VS wrong?

113 Views Asked by At

Having the following class, I protected it against null for Values.

public class Container
{
  public Guid Id { get; init; }
  public virtual IEnumerable<Measure> Measures { get; init; }
  public Dictionary<string, Measure[]> Measurement 
    => (Measures ?? Array.Empty<Measure>())
      .GroupBy(a => a.Type).ToDictionary(a => a.Key, a => a.ToArray());
}

public class Measure
{
  public string Name { get; set; }
  public string Type { get; set; }
}

For some reason, my IDE marks the coalescing as superfluous, claiming that the property will never be null (i.e. Measures??Array.Empty<Measure>() may be refactored to Measures).

public class Container
{
  public Guid Id { get; init; }
  public virtual IEnumerable<Measure> Measures { get; init; }
  public Dictionary<string, Measure[]> Measurement 
    => Measures
      .GroupBy(a => a.Type).ToDictionary(a => a.Key, a => a.ToArray());
}

When I followed that advice, a colleague pointed out that it's flawed. I agree with him but it's a bug in VS/R# is rearly a realistic explanation. More realistic is: it's us being wrong. So I sense that we're both missing something and that the IDE is right, somehow.

enter image description here

I can't explain how, though.

What I tried was to removing virtual, adding = default! and a few other alterations. Regardless, excuting in this in a fiddle, throws ArgumentNullException if the coalescing is removed.

2

There are 2 best solutions below

5
shingo On BEST ANSWER

The NRT document mentions:

Any variable where the ? isn't appended to the type name is a non-nullable reference type. That includes all reference type variables in existing code when you've enabled this feature.

Therefore, if nullable is enabled on the project, based on this standard the analyzer should assume that Measures will never be null.

FYI, if you have not initialized the Measures property, you should see a CS8618 warning, though you can ignore it. If you want to avoid ignoring this warning, you can add "nullable" to the "Treat specific warnings as error" in the project settings to report compilation errors.

1
rotabor On

It looks like very related to 'Nullable' project setting: enter image description here

UPD I was not able to reproduce IDE's message regardless of 'Nullable' setting.

Microsoft Visual Studio Community 2022 (64-bit) - Current Version 17.6.0

With 'Nullbale' is 'Enable':

1>------ Build started: Project: WinFormsApp3, Configuration: Debug Any CPU ------

1>C:\Users\TMSAdmin\source\WinFormsApp3\WinFormsApp3\Form1.cs(99,23,99,27): warning CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

1>C:\Users\TMSAdmin\source\WinFormsApp3\WinFormsApp3\Form1.cs(100,23,100,27): warning CS8618: Non-nullable property 'Type' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

1>C:\Users\TMSAdmin\source\WinFormsApp3\WinFormsApp3\Form1.cs(92,45,92,53): warning CS8618: Non-nullable property 'Measures' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

1>WinFormsApp3 -> C:\Users\TMSAdmin\source\WinFormsApp3\WinFormsApp3\bin\Debug\net6.0-windows\WinFormsApp3.dll

1>Done building project "WinFormsApp3.csproj".

========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========