5

以下行为背后的理性(如果有的话)是什么:

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

为什么比较运算符的行为与可空值的默认比较器不同?

更多奇葩:

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)
4

1 回答 1

3

<=并且>是提升的运算符,false如果任一值为 . 则返回null

对于关系运算符

< > <= >=

如果操作数类型都是不可为空的值类型并且结果类型是 bool,则存在运算符的提升形式。提升的形式是通过添加单个 ? 每个操作数类型的修饰符。如果一个或两个操作数为空,则提升的运算符产生值 false。否则,提升的运算符会展开操作数并应用底层运算符来生成 bool 结果。

由于比较器用于排序,因此它们需要总排序,null根据定义,比较小于所有其他值。这种需求优先于与比较运算符的一致性。与任何其他值比较时返回 0null是不可能的,这会违反传递性,因此设计人员必须选择要么发出错误,要么排序总是排序null为小于或大于任何其他值。在 .net 1 中,他们决定null为引用类型决定比其他所有内容都小,并且自然地,该决定延续到 .net 2 中的可空值类型。

这些之间的区别与NaN浮点的行为方式非常相似。例如NaN,不甚至不等于自身,所有比较运算符都返回 false。但是当使用一个比较器时NaN,它等于它自己并且小于除 之外的其他值null

Enumerable.Min返回最小的非空值,并且仅null在序列不包含非空值时返回。使用这样的函数null通常代表一个省略的值,并且您有兴趣找到最小的实际值。

于 2013-07-15T00:16:30.577 回答