在项目定义中使用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'`
在值上尝试相同操作时1.计数:
values1?[values1?.Count - 2]
如何解决这个问题?
values1[values1.Count - 2]
或
values1.Last();
基本上是函数调用,编译器不能确定它们在后续调用中产生相同的值(比如说,第一次调用Last()
时,它可能不会返回null,但第二次返回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;
}
问题是您正在直接访问Nullable<T>
的Value
属性。编译器不知道列表中最后一个和倒数第二个索引的值是否会在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;
我还使用索引简化了您的数组访问。
那么上面的代码中发生了什么
您的方法采用两个ILists
values1
和values2
,它们包含T?
的值(与Nullable<T>
相同,只是更短(。请注意,IList
实例本身不能为null(或者至少我们不希望它们为null(。因此,在列表本身之后,我们不需要任何null条件。因此不需要values1?[values1.Count - 2]
中values1
之后的?
。收到警告的原因是索引操作返回的元素可能为null。因此,我们在之后应用?
运算符,索引我们想要的元素。
由于?.
运算符,现在只有在上一次索引操作返回的值不为null的情况下,才继续执行CompareTo()
语句。由于CompareTo(object? obj)
无论如何都取一个可为null的值,因此我们不需要对comparand进行null检查。如果values1[^2]
(访问倒数第二个元素(返回的值为null,则不会对CompareTo()
进行求值,并且null > 0
将始终对int?
求值为false。这就是为什么我们不需要在if语句中进行显式的null检查。
第二行的作用完全相同。注意,int
与null
的任何比较都将返回false
。因此null < 0
为假。