首页 > 解决方案 > 使用外部库时 C# 8.0 可为空的引用类型的好处

问题描述

我目前正在将 ASP.NET Core 2.1 项目更新到 .NET 5,同时尝试利用一些较新的 C# 语言功能,例如:C# 8.0 的可为空引用类型

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

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

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

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


编辑(13-01-2021):

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

编辑(14-01-2021):

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

标签: c#c#-8.0nullable-reference-types

解决方案


推荐阅读