可空引用类型意外 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()
作为解决方法,但我想知道如何向编译器证明如果检查了singleContent
,x.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 可空值类型可能为带有临时变量的空的主要内容,如果未能解决你的问题,请参考以下文章
可空类型的 datagridview 组合框下拉列表中的空值
Kotlin空安全 ① ( Kotlin 的空安全机制 | 变量可空性 | 默认变量不可赋空值 | 声明可空类型变量 )