【问题标题】:Why does default comparer consider null to be less than a value为什么默认比较器认为 null 小于一个值
【发布时间】:2021-11-16 22:36:25
【问题描述】:

Compare(T? x, T? y) 的文档说:

返回:
一个有符号整数,表示 x 和 y 的相对值
小于零 - x 小于 y。
零 - x 等于 y。
大于零 - x 大于 y。

考虑这个例子:

using System;
using System.Collections.Generic;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine(Comparer<int?>.Default.Compare(null, 1)); // -1   ?huh?
        Console.WriteLine(Comparer<int?>.Default.Compare(-1, 1));   // -1
        Console.WriteLine(Comparer<int?>.Default.Compare(1, 1));    //  0
        Console.WriteLine(Comparer<int?>.Default.Compare(2, 1));    //  1
        
        Console.WriteLine((int?)null < 1);                          // False
        Console.WriteLine((int?)null == 1);                         // False
    }
}

所以null“小于”某个值。如果它返回一个不同的幻数(例如-2),或者抛出异常等等,我就不会那么惊讶了。

正如预期的那样,null &lt; 1 是假的,这似乎与上述相反。

这是有什么原因,还是只是需要注意的 API 怪癖?

【问题讨论】:

标签: c# types nullable


【解决方案1】:

它需要根据IComparable&lt;T&gt; / IComparer&lt;T&gt; 定义比较,并且它选择 null 比其他任何东西都小。这是指定的here。唯一的其他选择是抛出一个异常,大多数人会认为这是一件坏事,因为它会破坏任何带有空值的排序。

&lt; 运算符完全独立,当任一操作数为 null 时,它选择返回 false。尽管看起来不直观:CompareTo 和 &lt; 确实不需要完全一致。

【讨论】:

  • 我想可能是因为在这些接口之后将可空类型添加到语言中,所以他们硬塞进了逻辑(没有证据,只是一个疯狂的猜测)。但即便如此,你的解释更有意义——这只是一个设计惯例。
【解决方案2】:

这个实验会让你大吃一惊(就像我的一样):

int? a = null;
int b = 0;
if (a < b)
    log.Debug("null is smaller than 0");
else if (a == b)
    log.Debug("null is equal to 0");
else
    log.Debug("null is larger than 0");

输出:null is larger than 0
这并不意味着它更大,它只是意味着它不会更小:-))

但是现在,在监视窗口中查看这些值:

a     null   int?
b     0      int
a>b   false  bool
a<b   false  bool
a==b  false  bool

因此,显然,将 null 与实际值进行比较会得出虚假结果。

【讨论】:

  • 为什么会如此令人惊讶?如果我们想将澳大利亚的大小与完全未定义的实体 Unfoundia 进行比较,那么“更大”/“更小”/“相等”都不是有效的。
  • 根据stackoverflow.com/users/23354/marc-gravell 的回答,当两者之一是null 时,我希望a&gt;b 是true。
  • 你不能说某些东西比不存在的东西“更大”。另一个类比是将您的生日与一个不存在的人进行比较。你不是在那个人之后出生的,因为不存在的人从来没有存在过,你也没有在那个人之前出生,因为那个人也永远不会出生。显然,那个人也没有透露你的生日。
  • @Dominique no,c# 规范第 6.4.2 节(提升的转换运算符)和 7.3.7(提升的运算符)定义了使用可空类型的此类运算符的规则,它被定义为返回 false这里
  • 薛定谔的猫是死是活?是的。 :-P 他们只是选择了一种约定。
猜你喜欢
  • 2012-01-18
  • 2018-11-17
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 2019-07-06
  • 1970-01-01
  • 2018-05-22
相关资源
最近更新 更多