可空引用类型意外 CS8629:可为空的值类型可能为空,使用临时变量

10
在一个使用 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?

1
这里的“正确”解决方法是使用该死的运算符——x.DataInt!.Value - canton7
4
这是分析过程已知的限制。这在 https://github.com/dotnet/roslyn/issues/34800 中讨论过(当引入临时变量时可能会出现可空警告)。 - Julien Couvreur
1
@JulienCouvreur 这不完全是同一个问题,但我认为它将落入相同的响应范畴,需要更深入的分析支持,并且超出了 C# 8 的范围。 - Lasse V. Karlsen
我同意@canton7的观点,这很可能是使用!运算符的一个好案例。但是,你需要小心,以免在你使用它的两个当前位置之间意外覆盖 singleContent 变量的值,因为 ! 运算符将无法捕获意图的变化。 - Lasse V. Karlsen
1
@LasseVågsætherKarlsen Julien是可空类型的设计师之一。因此,无论问题措辞是否匹配,他都是最有资格编写对这个问题的良好回答(唠叨唠叨)。 - Panagiotis Kanavos
显示剩余4条评论
1个回答

4

这只是一个临时答案,直到可空引用类型设计者之一Julien Couvreur发布最终答案(催促)。我在这里发布这篇文章,因为C# 8发布后该问题将再次被提出。

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

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

也许我们可以在.NET Conf 2019期间在线向他或Mads Torgersen询问发布日期(完全不是催促)


我在评论中说这不是完全相同的问题的原因是,别名(aliasing)和数据依赖性不同。别名意味着你为同一件事引入另一个变量,比如 var x = y;;而数据依赖性则需要流分析,比如 var x = y != null;。虽然我可能错了,它们可能被认为是相同的,但自从我上次看编译器设计及其术语以来已经过了很长时间了。无论如何,它们都归结于同一个广泛的原因,即 C# 8 中的代码分析还不够复杂(至少目前是这样)。 - Lasse V. Karlsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接