对其中一些为null的IComparable对象进行排序

| 大多数人在编写实现IComparable 的引用类型(类)时,都会使用null小于任何实际对象的约定。但是,如果您尝试使用相反的约定,则会发生一些有趣的事情:
using System;
using System.Collections.Generic;

namespace SortingNulls
{
  internal class Child : IComparable<Child>
  {
    public int Age;
    public string Name;

    public int CompareTo(Child other)
    {
      if (other == null)
        return -1; // what\'s your problem?

      return this.Age.CompareTo(other.Age);
    }

    public override string ToString()
    {
      return string.Format(\"{0} ({1} years)\", this.Name, this.Age);
    }
  }

  internal static class Program
  {
    private static void Main()
    {
      var listOfChilds = new List<Child>
      {
        null,
        null,
        null,
        null,
        new Child { Age = 5, Name = \"Joe\" },
        new Child { Age = 6, Name = \"Sam\" },
        new Child { Age = 3, Name = \"Jude\" },
        new Child { Age = 7, Name = \"Mary\" },
        null,
        null,
        null,
        null,
        new Child { Age = 7, Name = \"Pete\" },
        null,
        new Child { Age = 3, Name = \"Bob\" },
        new Child { Age = 4, Name = \"Tim\" },
        null,
        null,
      };

      listOfChilds.Sort();

      Console.WriteLine(\"Sorted list begins here\");
      for (int i = 0; i < listOfChilds.Count; ++i)
        Console.WriteLine(\"{0,2}: {1}\", i, listOfChilds[i]);
      Console.WriteLine(\"Sorted list ends here\");
    }
  }
}
运行上面的代码时,您会看到空引用未按预期排序。显然,在将A与B进行比较时,如果A是一个对象,而B为空,则使用用户定义的比较,但是相反,如果A为空,并且B是一个对象,则使用某种BCL比较。 这是一个错误吗?     
已邀请:
        不,这不是错误。实现
IComparable<Child>
CompareTo
方法是在
Child
类上定义的。换句话说,如果您必须对一种类型调用一个方法以进行比较。 如果要比较的“ 3”项之一为空,如何在其上调用“ 1”? 请注意,根据IComparable的定义: \“按照定义,任何对象的比较都大于(或遵循)空引用(在Visual Basic中为Nothing),并且两个空引用彼此比较相等。\” 这解释了您观察到的结果。 解决方案是委托其他某个类进行比较。请参阅IComparer界面。     
        如果
this
null
,而您尝试评估
this.Age.CompareTo(other.Age);
,将会发生什么?实际上,在C#中,
this
永远不可能是
null
。 至于询问它是否是错误,请参阅此博客文章。     
        类型
T
的默认值
Comparer<T>
必须考虑第一个元素(让我们将其称为A)是
null
的情况。假设它看起来像这样:
if (ReferenceEquals(a, null))
{
    return -1;
}

return a.CompareTo(b);
这基于ѭ15的文档:   此方法使用默认的比较器   T型的to16ѭ   确定列表元素的顺序。 可以说,如果两个元素都是
null
,则最上一步只能返回
0
,否则使用
b.CompareTo(a)
的相反值。 不过,我不会真正将其称为错误。这只是要注意的事情。     
        不,您的代码带有“错误”,因为它没有遵循定义“ 20”的标准:IComparable 具体来说:根据定义,任何对象的比较值大于(或跟随)
null
,并且两个
null
引用的相等。 在您的示例中,您定义的对象是要比较(小于或等于)
null
的对象,这恰恰与应做的相反。     

要回复问题请先登录注册