首页 > 解决方案 > 可空接口不触发 CS8602

问题描述

我现在遇到过几次启用可空且标记为可空接口类型的属性或字段(带有附加的?),然后如果我在没有空检查的情况下使用该属性或字段,我不会收到任何错误。(我希望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?未标记为可能为 Nullable,就像具体类型的属性和字段一样?

标签: c#.net-coreroslynroslyn-code-analysisomnisharp

解决方案


编译器对变量是否可以具有空值的看法与变量的类型是类还是接口无关 - 它是否先前被取消引用。

您收到以下两行的警告:

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

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

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

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


推荐阅读