【问题标题】:Weird nullable comparison behavior奇怪的可空比较行为
【发布时间】:2013-07-14 23:59:18
【问题描述】:

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

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)

【问题讨论】:

  • 你的问题有问题。 Comparer.Default.Compare(1, a) 无法返回 True,因为它是 Integer
  • @AndréPena:好电话。我已经修复了评论
  • 好问题。我一直想写这篇博客。

标签: c# linq nullable comparator


【解决方案1】:

&lt;=&gt; 是提升运算符,如果其中一个值为 null,则返回 false

对于关系运算符

&lt;&gt;&lt;=&gt;=

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

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

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

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

【讨论】:

  • TIL 提升了运营商。
猜你喜欢
  • 1970-01-01
  • 2014-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 2017-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多