使用外部库时 C# 8.0 可为空引用类型的好处

问题描述

我目前正在将 ASP.NET Core 2.1 项目更新到 .NET 5,同时尝试利用一些较新的 C# 语言功能,例如:C# 8.0's nullable reference types>

我尝试为我的一个项目启用它并开始处理一些弹出的警告。在一个地方,我正在压缩一个文件夹,其中有一些调试日志:

var dirInfo = _fs.DirectoryInfo.FromDirectoryName(absPath);
var subEntries = dirInfo.GetFileSystemInfos();
foreach (var info in subEntries)
{
    var isDirInfo = IsDirectory(info.Attributes);
    _logger.Debug("Adding item to archive with parameters: type={type},name={name},bytes={size}",isDirInfo ? "directory" : "file",info.Name,isDirInfo ? 0 : (info as FileInfoBase).Length);
    //                   ~~~~~~~~~~~~~~~~~~~~
    // CS8602: Dereference of a possibly null reference.

    AddToZip(archive,info.FullName,Path.Join(entryPath,info.Name),isDirInfo);
}

在上面的代码段中,_fs 是来自 System.IO.Abstractions 库的 IFileSystem。上面的确切警告与此处的实际问题无关,但我对如何正确修复它的调查让我想知道为什么在代码段的第二行没有显示警告。 FromDirectoryName 签名中没有任何内容表明它不能为空,因为库尚未使用此功能。因此,我希望编译器假定 dirInfo 可能为 null 并在尝试在第二行取消引用时显示警告。 (让我们暂时假设 FromDirectoryName 将返回 null 而不是在 absPath 不存在时抛出异常 - 这是我目前最好的现实世界示例)

据我在互联网上了解到的情况,这是预料之中的。换句话说:因为 FromDirectoryName 的返回类型是 IDirectoryInfo 而不是 IDirectoryInfo?,编译器的行为就好像 dirInfo 永远不会为 null。我不知道这是设计选择还是技术限制,但这让我想知道这种新的可为空引用类型的好处是什么。对我来说,似乎无法依靠编译器来警告您使用从外部库返回的值会破坏这个“新”功能的很大一部分,因为它可能会导致您忽略潜在的空引用异常。

我是否错误地解释了上述代码片段中编译器的行为,或者我只是在依赖多个外部库的项目中使用可空引用类型的方法错误?我希望您能帮助启发我在这种情况下如何使用此语言功能


编辑 (13-01-2021):

blog post from Microsoft 中,他们甚至指出您不能相信编译器会解释尚未启用该功能的库中的方法签名。它强化了我的理论,即除非您正在处理一个只有很少 3rd 方库的项目,否则您很可能会浪费时间实现此功能,但仍然无法获得空安全代码

编辑 (14-01-2021):

添加了可重现的示例:https://github.com/Xerillio/csharp8-nrt-test

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)