C# 编译器警告输出中可能出现可空性检查错误

问题描述 投票:0回答:1
Type type = typeof(Program);
type = type.BaseType; // [CS8600] Converting null literal or possible null value to non-nullable type.
    
do
{
    type = type.BaseType; // [CS8602] Dereference of a possibly null reference. + [CS8600] Converting null literal or possible null value to non-nullable type.
}
while(true);

在上面的程序中,我希望编译器发出相同的警告(

BaseType
可以为空,因此不能将其分配给
type
变量)。而实际上在第二种情况下,我得到了另一个对我来说似乎错误的错误(
type
变量根据定义不能为空)。

这是编译器中的某种错误吗?或者相反,编译器“非常聪明”,并且发现我确实尝试将 null 分配给不可为 null 的变量,因为这只是一个警告,所以现在它会显示两个警告?

c# nullable
1个回答
0
投票

在这种情况下,编译器确实“特别聪明”。

对于循环中的行

type = type.BaseType;
,它看到您正在将
BaseType
(可能为空)分配给不应该为空的变量
type
。这将产生 CS8600,其原因与 CS8600 的第一个实例相同。

看到

type
中的表达式
type.BaseType
可能为空。这是因为编译器可以看到您刚刚为
type
分配了一个可能为空的东西。因此,
type.BaseType
取消引用可能为空的事物,并且可能会抛出
NullReferenceException
。这会导致 CS8602。

在整个方法中跟踪每个变量的“空状态”。有关编译器如何进行空跟踪的更多信息,请参阅此处的文档。这里我在程序的每一行注释了

type
的空状态:

Type type = typeof(Program);

// not null, because typeof(Program) never produces null

type = type.BaseType;

// maybe null, because BaseType is of type 'Type?'
    
do
{
    // still maybe null here

    type = type.BaseType;

    // still maybe null here
}
while(true);

// not null, because this line is unreachable :)
© www.soinside.com 2019 - 2024. All rights reserved.