问题描述
在启用了可空引用类型的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>