roslyn: Debug.Assert() causes wrong nullability in analysis when targeting older TFMs

With the following source code:

class Foo
{
    public void Bar()
    {
        string s = "";
        Debug.Assert(s != null, "No connector");
        Console.WriteLine(s.Length);
    }
}

The preview8 compiler generates warning CS8602: Dereference of a possibly null reference. on s.Length. If the assertion is removed the warning disappears.

This only happens when targeting netstandard2.0 (and possible other older TFMs) - with netstandard2.1 and netcoreapp3.0 the warning is not generated. I know C# 8 is officially supported only on the new TFMs, but this seems like quite an odd bug that’s probably worth investigating.

csproj:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <Nullable>enable</Nullable>
        <LangVersion>8.0</LangVersion>
    </PropertyGroup>
</Project>

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 4
  • Comments: 17 (12 by maintainers)

Most upvoted comments

How is a Debug.Assert(s != null) telling the compiler that s can be null? The point is that the type of s is string, not string?.

s != null is telling the compiler that it can be null. If you know that it can’t be null, why do you add null checks?

How is a Debug.Assert(s != null) telling the compiler that s can be null?

I assume the expression s != null indicates to flow analysis that s might be null on the ‘false’ path. Otherwise you could have cases like this:

public void Method(string value) {
  if (value is null) {
    // According to the static type of `value`, we don't have a warning here:
    Console.WriteLine(value.ToString());
    return;
  }
}