可空接口不触发 CS8602

问题描述

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

我不确定这是 Roslyn 错误还是我不太了解的东西。

附加信息:

  • .NET 5
  • C# 9

Sample code


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?属性或字段没有像具体的类型化属性和字段那样被标记为可能为 Nullable?

解决方法

的变量是否可具有空值或没有编译器的视图无关与变量的类型是一个类或是否它是一个接口 - 这是无论它是先前已被解除引用

您接收警告,以下两行:

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

...因为这是第一次每个那些变量的已取消引用。但是编译器假定如果两个那些线都没有出现任何的异常,则相同的变量的用途稍后执行的:

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

...将被罚款。无论变量可以通过在执行流程这点空,因为早期行的,否则人会抛出异常。 (其中“空性流动”并不考虑到另一个线程可以改变在中间的变量的值的可能性。)