可空接口不触发 CS8602

Nullable Interface does not trigger CS8602

我现在遇到过几次启用 nullable 并且 属性 或字段标记为可空接口类型(附加 ?),那么如果我在没有空检查的情况下使用 属性 或字段,我不会收到任何错误。 (我希望 CS8602 - Dereference of a possibly null reference.,并且在具体类型属性和字段中我确实收到此错误)。

我不确定这是 Roslyn 错误还是我没有充分理解的问题。

附加信息:


namespace dotnet_scratch {

    interface IFoo {
        string? name { get; set; }

        void fooAction ();
    }

    interface IFooGeneric<T> {
        string? name { get; set; }
        void fooAction( );
    }

    public class FooClass {
        IFoo? fooInterface;
        IFooGeneric<string>? fooInterfaceString;

        FooClass? fooClass;

        void doStuff( ) {
            System.Console.WriteLine( fooInterface.name );
            System.Console.WriteLine( fooInterfaceString.name );
            fooInterface.fooAction();
            fooInterfaceString.fooAction();
            fooClass.fooAction();
        }
        void fooAction () {}
    }
}

在捕获中,三个突出显示的错误被标记为:

(field) IFooGeneric<string>? FooClass.fooInterfaceString
'fooInterfaceString' may be null here.

Dereference of a possibly null reference. [dotnet_scratch]csharp(CS8602)

另外将鼠标悬停在 fooInterface.fooAction()fooInterfaceString.fooAction() 上说: 'fooInterfaceString' 在这里不为空。

我的问题是为什么 属性 或标记为 IInterfaceType? 的字段不像具体类型的属性和字段那样被标记为潜在可空?

编译器对变量是否可以有 null 值的看法与变量的类型无关 class 或者它是否是一个接口 - 它是否以前被取消引用。

您收到了这两行的警告:

System.Console.WriteLine( fooInterface.name );
System.Console.WriteLine( fooInterfaceString.name );

... 因为这是第一次取消对每个变量的引用。但是编译器假定如果 那些 行都已执行而没有抛出异常,那么以后使用相同的变量:

fooInterface.fooAction();
fooInterfaceString.fooAction();

...会没事的。到执行流程中的这一点,两个变量都不能为空,否则前面的行之一会抛出异常。 (“可空性流程”没有考虑到另一个线程可能会在中间更改变量值的可能性。)