可空引用类型意外 CS8629 可空值类型可能为带有临时变量的空

Posted

技术标签:

【中文标题】可空引用类型意外 CS8629 可空值类型可能为带有临时变量的空【英文标题】:Nullable reference types unexpected CS8629 Nullable value type may be null with temporary variables 【发布时间】:2019-12-17 08:47:02 【问题描述】:

在一个 C# 8 项目中,我正在使用可为空的引用类型,并且收到了一个意外的(或至少对我来说是意外的)CS8629 警告,

bool singleContent = x.DataInt != null;
bool multiContent = x.DataNvarchar != null;

if (singleContent && multiContent)

    throw new ArgumentException("Expected data to either associate a single content node or " +
        "multiple content nodes, but both are associated.");


if (singleContent)

    var copy = x.DataInt.Value; // CS8629 here
    newPropertyData.DataNvarchar = $"umb://type.UdiType/Nodes[copy].UniqueId.ToString("N")";

我决定使用GetValueOrDefault() 作为解决方法,但我想知道如何向编译器证明如果检查了singleContentx.DataInt 不能为空。

注意x.DataInt的类型是int?

【问题讨论】:

这里“正确”的解决方法是使用该死的操作符 -- x.DataInt!.Value @canton7 所以我明白了。我怎么会错过一个叫做该死的操作员的东西……该死的。我想今天早上我的大脑不太好。 这是分析的已知限制。这在github.com/dotnet/roslyn/issues/34800(引入 tmp 变量时的可空警告)中进行了讨论 @JulienCouvreur 这不是完全相同的问题,但我认为它会属于相同的响应,它需要更深入的分析支持并且超出了 C# 8 的范围。 @LasseVågsætherKarlsen Julien 是可空类型的设计者之一。所以无论问题的措辞是否匹配,他最有资格为这个问题写一个好的答案(nag nag) 【参考方案1】:

这只是一个临时答案,直到可空引用类型的设计者之一 Julien Couvreur 发布了明确的答案(唠叨)。我在这里发布这个问题是因为一旦 C# 8 发布,这个问题就会再次被问到。

正如 Julien 在 3 个 Github 问题 #34800、#37032 和 #36149 中回答的那样,这是 C# 8 分析器的已知限制,超出了 C# 8 的范围。

这需要别名分析(这里只是猜测)意味着分析器将能够分析别名表达式,即其结果“隐藏”在临时变量(也可能是参数?)后面的表达式。

也许我们可以在.NET Conf 2019 期间发布 .NET Core 3 时在线询问他或 Mads Torgersen 关于发布日期(完全没有唠叨)

【讨论】:

我在评论中说这不是完全相同的问题的原因是别名,这意味着您为同一事物引入另一个变量,例如var x = y;,与数据依赖关系不同,比如var x = y != null;,需要流量分析。不过我可能是错的,它们可以被认为是相同的,自从我查看编译器设计及其术语以来已经很久了。无论哪种方式,它们都归结为同一个广泛的原因,代码分析在 C# 8 中还没有那么复杂。

以上是关于可空引用类型意外 CS8629 可空值类型可能为带有临时变量的空的主要内容,如果未能解决你的问题,请参考以下文章

C#进阶系列18 可空值类型

可空类型的 datagridview 组合框下拉列表中的空值

Kotlin空安全 ① ( Kotlin 的空安全机制 | 变量可空性 | 默认变量不可赋空值 | 声明可空类型变量 )

避免可空值类型的 Value 属性?

如何将空值传递给 WebAPI 中的可空类型

可空类型产生警告,因为项目已启用可空引用类型