对IComparable对象进行排序,其中一些对象为null
大多数人在编写实现IComparable 的refence类型(类)时,使用null比任何实际对象少的约定。 但是如果你尝试使用相反的约定,会发生一些有趣的事情:
using System; using System.Collections.Generic; namespace SortingNulls { internal class Child : IComparable { 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 { 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是null,则使用用户定义的比较,但如果相反A为空且B是对象,则使用某些BCL比较。
这是一个错误吗?
不,这不是一个错误。 实现IComparable
CompareTo
方法在您的Child
类中定义。 换句话说,如果您必须在其中一个类型上调用方法以进行比较。
如果要比较的其中一个Child
项为空,您如何在其上调用CompareTo
?
请注意,从IComparable的定义:
“根据定义,任何对象都比大于(或跟随)空引用(在Visual Basic中为Nothing),并且两个空引用相互比较相等。”
这解释了您观察到的结果。
解决方案是委托其他类来执行比较。 请参阅IComparer接口。
如果你试图评估this.Age.CompareTo(other.Age);
会发生什么this.Age.CompareTo(other.Age);
如果this
是null
? 实际上, this
在C#中永远不会为null
。
至于询问它是否是一个错误,请参阅此博客文章 。
类型T
的默认Comparer
必须考虑第一个元素(我们称之为A)为null
。 让我们说它看起来像这样:
if (ReferenceEquals(a, null)) { return -1; } return a.CompareTo(b);
这是基于List
的文档 :
此方法使用类型T的默认比较器
Comparer(Of T).Default
来确定列表元素的顺序。
可以说,如果两个元素都为null
,则最高步骤只能返回0
,否则使用与b.CompareTo(a)
相反的b.CompareTo(a)
。
不过,我不会把它称为bug 。 这只是需要注意的事情。
不,它的代码有“bug”,因为它不符合定义IComparable.CompareTo()
的标准: IComparable
具体来说: 根据定义,任何对象都会比较大于(或跟随) null
,并且两个null
引用相互比较相等。
在您的示例中,您定义要比较小于(或先于) null
,这恰好与应该如何进行比较。