解决 Net Core 6 中值 1.Count 上的“Nullable value type may be null”

Posted

技术标签:

【中文标题】解决 Net Core 6 中值 1.Count 上的“Nullable value type may be null”【英文标题】:Solve "Nullable value type may be null" on values1.Count in NetCore 6 【发布时间】:2021-11-12 11:31:14 【问题描述】:

在项目定义中使用 NetCore 6 和 <Nullable>enable</Nullable>

protected Boolean CrossBelow<T>(IList<Nullable<T>> values1, IList<Nullable<T>> values2) where T : struct, IComparable 

  if (values1[values1.Count - 2] == null || values1.Last() == null || values2[values1.Count - 2] == null || values2.Last() == null)
    return false;

  return values1[values1.Count - 2].Value.CompareTo(values2[values2.Count - 2].Value) > 0 && values1.Last().Value.CompareTo(values2.Last().Value) < 0;

 

但我收到了警告:

Nullable value type may be null

在一些地方,例如:

values1[values1.Count - 2]

我可以使用以下方法解决部分问题:

values1?[values1.Count - 2]

但是我得到编译错误

`cannot convert from 'int?' to 'int'` 

在 values1.Count 上尝试相同的操作时:

values1?[values1?.Count - 2]

如何解决?

【问题讨论】:

问题是可空流分析显然不够聪明,无法发现您对那些Nullable&lt;T&gt; 值进行了正确的空检查。请注意错误是“Nullable value type may be null”——IList 是一个引用类型,因此与此无关。您可以使用null-forgiving operator !: values1[values1.Count - 2].Value!.CompareTo(values2[values2.Count - 2].Value!) 等将其关闭 请注意,如果您使用的是 C# 8 或更高版本,您可以使用values1[^2] 代替values1[values1.Count - 2],以及values1[^1] 代替values1.Last() 【参考方案1】:

类似的东西:

values1[values1.Count - 2]

values1.Last();

基本上是函数调用,编译器不能确定它们在后续调用中产生相同的值(比如第一次调用Last()它可能返回不为空,但第二次返回null,编译器不知道它是在你的情况下不可能)。只需引入变量,即使没有这些警告也不会造成伤害:

protected Boolean CrossBelow<T>(IList<Nullable<T>> values1, IList<Nullable<T>> values2) where T : struct, IComparable

    var v1Prev = values1[values1.Count - 2];
    var v1Last = values1.Last();
    var v2Prev = values2[values2.Count - 2];
    var v2Last = values2.Last();
    if (v1Prev == null || v1Last == null || v2Prev == null || v2Last == null)
        return false;

    return v1Prev.Value.CompareTo(v2Prev.Value) > 0 && v1Last.Value.CompareTo(v2Last.Value) < 0;

【讨论】:

节省一些垂直空间:var (v1Prev, v1Last) = (values1[^2], values1[^1])【参考方案2】:

问题是您正在直接访问Nullable&lt;T&gt;Value 属性。编译器不知道您的列表中最后一个和倒数第二个索引的值是否会在您的 null 检查和您在 return 语句中访问这些元素时发生变化。

这里最简单的解决方案是使用null-conditional operator ?.。这将允许您甚至删除显式的 null 检查,因为现在一切都在一次发生:

protected bool CrossBelow<T>(IList<T?> values1, IList<T?> values2) where T : struct, IComparable =>
       values1[^2]?.CompareTo(values2[^2]) > 0
    && values1[^1]?.CompareTo(values2[^1]) < 0;

我还使用indices 简化了您的数组访问。

那么上面的代码发生了什么?

您的方法需要两个 ILists values1values2,其中包含 T? 的值(与 Nullable&lt;T&gt; 相同,只是更短)。请注意,IList 实例本身不能为空(或者至少我们不希望它们为空)。因此,列表本身之后我们不需要任何空条件。所以不需要values1?[values1.Count - 2]values1之后的?。您收到警告的原因是索引操作返回的元素可能为空。因此,我们应用? 运算符我们索引了我们想要的元素。

感谢?. 运算符的执行现在仅在前一个索引操作返回的值不为空时才继续执行CompareTo() 语句。由于CompareTo(object? obj) 无论如何都采用可空值,因此我们不需要对比较数进行空检查。如果values1[^2](访问倒数第二个元素)返回的值 null,那么CompareTo() 将不会被评估,null &gt; 0 将始终为int? 评估为false。这就是为什么我们不需要在 if 语句中显式检查 null。

第二行完全一样。请注意,intnull 的任何比较都将返回 false。所以null &lt; 0 是假的。

【讨论】:

以上是关于解决 Net Core 6 中值 1.Count 上的“Nullable value type may be null”的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC Core/6:多个提交按钮

.Net Core 6 web api jwt 一直 401 Postman返回WWW-Authenticate Bearer没有其他提示的解决方法

Blog.Core开源完成升级.NET 6.0

ASP.Net Core 6,SPA,端点 - 我无法从 http get 请求调用控制器

ASP.NET Core 6框架揭秘实例演示[11]:诊断跟踪的几种基本编程方式

《ASP.NET Core 6框架揭秘》实例演示[19]:数据加解密与哈希