以下行为背后的理性(如果有)是什么:
int? a = null;
Console.WriteLine(1 > a); // prints False
Console.WriteLine(1 <= a); // prints False
Console.WriteLine(Comparer<int?>.Default.Compare(1, a)); // prints 1
为什么比较运算符的行为与默认的nullables比较器不同?
更奇怪:
var myList = new List<int?> { 1, 2, 3, default(int?), -1 };
Console.WriteLine(myList.Min()); // prints -1 (consistent with the operators)
Console.WriteLine(myList.OrderBy(i => i).First()); // prints null (nothing) (consistent with the comparator)
Console.WriteLine(new int?[0].Min()); // prints null (nothing)
Console.WriteLine(new int[0].Min()); // throws exception (sequence contains no elements)
答案 0 :(得分:3)
<=
和>
是提升的运算符,如果值为false
,则返回null
。
对于关系运算符
<
>
<=
>=
如果操作数类型都是非可空值类型且结果类型为bool,则存在提升形式的运算符。提升形式是通过添加一个?每个操作数类型的修饰符。如果一个或两个操作数为空,则提升的运算符将生成值false。否则,提升的运算符会解包操作数并应用基础运算符来生成bool结果。
由于比较器用于排序,因此需要总排序,其中null
按定义比较小于其他每个值。这种需求优先于比较运算符的一致性。将null
与任何其他值进行比较时返回0是不可能的,这会违反传递性,因此设计者必须选择发出错误,或者排序总是将null
排序为比任何其他更小或更大值。在.net 1中,他们认为null
小于其他所有参考类型的决定,自然这个决定延续到.net 2中的可空值类型。
这些差异与NaN
在浮点上的行为非常相似。例如,NaN
甚至不等于自身,并且所有比较运算符都返回false。但是当使用比较器NaN
等于它自己并且小于除null
之外的其他值时。
Enumerable.Min
返回最小的非空值,如果序列不包含非空值,则仅返回null
。使用这样的函数null
通常代表一个省略的值,并且您有兴趣找到最小的实际值。