解决NetCore 6中values1.Count上的“Nullable值类型可能为null”

Mig*_*ura 7 c# .net-core c#-10.0

使用 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;

} 
Run Code Online (Sandbox Code Playgroud)

但我收到警告:

Nullable value type may be null
Run Code Online (Sandbox Code Playgroud)

在一些地方,例如:

values1[values1.Count - 2]
Run Code Online (Sandbox Code Playgroud)

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

values1?[values1.Count - 2]
Run Code Online (Sandbox Code Playgroud)

但我收到编译错误

`cannot convert from 'int?' to 'int'` 
Run Code Online (Sandbox Code Playgroud)

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

values1?[values1?.Count - 2]
Run Code Online (Sandbox Code Playgroud)

怎么解决这个问题呢?

Fre*_*eft 1

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

这里最简单的解决方案是使用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;
Run Code Online (Sandbox Code Playgroud)

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

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

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

感谢运算符的执行,如果前一个索引操作返回的值不?.为空,则现在只会继续执行该语句。CompareTo()无论如何,由于CompareTo(object? obj)采用可为空的值,因此我们不需要对比较数进行空检查。values1[^2]如果(访问倒数第二个元素)返回的值为null,则CompareTo()不会对其求值,并且null > 0对于int?. 这就是为什么我们不需要在 if 语句中进行显式 null 检查。

第二行的作用完全相同。int请注意,与 的任何比较都null将返回false。所以null < 0是假的。