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

Posted

技术标签:

【中文标题】可空类型产生警告,因为项目已启用可空引用类型【英文标题】:Nullable type producing warnings since project has enabled nullable reference types 【发布时间】:2022-01-08 05:35:43 【问题描述】:

我只有在启用可空引用类型后才会收到警告,但具体示例实际上是旧的 Nullable<T> 类型:

var nullableItems = new List<int?>();

var actualNonNullValues = nullableItems.Where(x => x.HasValue)
                                       .Select(x => x.Value)
                                       .ToList();

所以我整理了所有的空值,只想要实际的非空项。但是,.Select(x =&gt; x.Value) 部分会给我一个关于x 可能在这里为空的编译器警告。逻辑上不是,但是对于编译器来说,类型还没有改变,仍然是int?

我知道我可以通过将! 应用于x 来告诉编译器闭嘴,但看起来我作弊了。在我使用的其他语言中,不得不退回到这种做法被认为是不好的做法,并且意味着你做错了什么。

我还有哪些其他选择?我能比在这里使用! 做得更好吗?

【问题讨论】:

您不必使用!,但它不会“更好”。有时! 只是您应该使用的东西。否则它会从语言中删除。 id 是什么?我在代码中没有看到。请记住,它是可空的 reference 类型,而 int? 是可空值类型,因此警告与 int? 部分无关。 @madreflection 抱歉,我重命名了示例。 x 在我的实际代码中被命名为 id 。我编辑了我的帖子。并且警告绝对是关于 Nullable 项目的。可为空的引用类型没有属性 .HasValue 和 .Value。 编译器不评估你的谓词,它不知道它是否是一个int?或 Where 正在返回的 int。 @AbdelkrimBournane 因为int?.Valueint,而actualNonNullValues 的推断类型正确的是List&lt;int&gt;,而不是List&lt;int?&gt; 【参考方案1】:

Select(x =&gt; x.Value) 中,x 的类型为int?,因此编译器会立即警告您在该类型上调用.Value 可能会抛出异常。

这没有多大意义,因为您已经在 .Where(x =&gt; x.HasValue) 中检查了可空性。不幸的是,C# 编译器目前不理解 Select 将只接收非空值,因为它的上下文不理解 Where 方法语义。

你唯一的选择是!,因为它说“我知道我在这里做什么。”

有一个语言问题跟踪此:https://github.com/dotnet/csharplang/issues/3951

【讨论】:

以上是关于可空类型产生警告,因为项目已启用可空引用类型的主要内容,如果未能解决你的问题,请参考以下文章

如何将所有 C# 8 可空引用警告视为错误?

可空引用类型的注释只能在“#nullable”上下文中的代码中使用

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

.NET Framework 项目中的可空引用类型不能与 IntelliSense 一起使用

何时在启用可空引用类型的情况下对参数进行空检查

未从 FirstOrDefault 公开的可空引用类型信息