将未初始化的数组传递给期望非空IEnumerable的方法不会导致编译警告或错误

问题描述

在启用了可空引用类型的C#8中,为什么以下内容不会引发编译器警告或错误

var strings = new string[1];
    
LogList(strings);
    
public void LogList(IEnumerable<string> strings) {
    foreach(var s in strings) {
        Console.WriteLine(s.ToString());
    }
}

我期望编译器警告或错误,因为该数组具有未初始化的元素,而String中的IEnumerable<String>是不可为空的。而是在调用s.ToString()时在运行时得到NullReferenceException。

如果我指示数组元素可为空,string?[],或使用具有可为空字符串的集合,List<string?>,则编译器警告我有关将其传递给LogList的期望一个不为空字符串的IEnumerable(不为null)。为什么上面的代码示例未生成类似的警告?

我在SO上浏览了许多有关可为空的引用类型的问题,但没有一个问题专门回答这个问题。

(在LINQPad 6.9.15中测试的代码

解决方法

在此代码var strings = new String[1];中,strings不是null,而是有效的IEnumerable<string>对象,其中第一个条目为null。因此,要使strings为空,您可以这样做string[] strings = null;

然后,当您通过启用可为空的引用类型运行应用程序时,编译器不会引发异常,而是会引发警告。 (如第一个屏幕截图所示)。

要获取错误信息,请在<PropertyGroup>内的.csproj文件中添加以下条目

    <Nullable>enable</Nullable>
    <WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>

enter image description here