Search code examples
c#.netnullable-reference-types

C# Null Static Analysis False Negative?


I am working in a project with nullable annotation context enabled, but we have a dependency on a library with nullable annotation context disabled.

Simplified example of the static analysis behavior I'm seeing in our project:

class Something
{
    static void Main(string[] args)
    {
        Foo foo = new();
        Console.WriteLine("foo.Bar: " + foo.Bar); // Null static analysis claim: 'Bar' is not null here. Runtime behavior: 'Bar' is null
    }
}

#nullable disable
class Foo
{
    public string Bar { get; set; }
}

My question is: is this static analysis behavior expected? It would be great to be able to rely on the null static analysis features to reason about our code & omit unnecessary null checks, but this is giving me doubts.


Solution

  • Yes, this is by design. When you have a code compiled with NRT disabled you will get nullable-oblivious state. From Nullable contexts section of the docs:

    The nullable annotation context determines the compiler's behavior. There are four values for the nullable annotation context:

    • disable: The code is nullable-oblivious. Disable matches the behavior before nullable reference types were enabled, except the new syntax produces warnings instead of errors.

    From the Nullable reference types (NRTs) docs:

    Reference type variables in code compiled in a disabled context are nullable-oblivious. ... However, the default state of a nullable-oblivious variable is not-null.

    And from Understand contexts and warnings:

    Each variable has a default nullable state that depends on its nullability:

    • Nullable variables have a default null-state of maybe-null.
    • Non-nullable variables have a default null-state of not-null.
    • Nullable oblivious variables have a default null-state of not-null.