在List .Sort()方法中,是否与自身进行了比较?

如果我将自定义IComparer传递给List的Sort()方法的实例,是否会使用相同的项调用比较器的Compare(x,y)方法?

即。 是否有可能调用Compare(x,x)

编辑:对列表中的项目不同的情况更感兴趣

我写了一个测试程序来试试。 看起来它实际上比较()相同的元素与自身(至少相同的项目两次调用Compare()两次)。 在这个程序中,使用参数(2,2)调用Compare()。

 using System; using System.Collections.Generic; static class Program { class MyComparer : Comparer { public override int Compare(int x, int y) { Console.WriteLine("Compare(" + x + ", " + y + ")"); if (x < y) return -1; if (x > y) return 1; return 0; } } static void Main() { MyComparer comparer = new MyComparer(); List list = new List { 1, 2, 3 }; list.Sort(comparer); return; } } 

输出是:

 Compare(1, 2) Compare(1, 3) Compare(2, 3) Compare(1, 2) Compare(2, 2) Compare(2, 3) Compare(2, 2) 

来自文档 :

此方法使用Array.Sort,它使用QuickSort算法。

QuickSort永远不会将项目与自身进行比较。 QuickSort的一些实现将项目与自身进行比较。 如果该项目在列表中出现多次,也会发生这种情况。

无论哪种方式,为了使您的比较函数成为正确的,良好的比较函数,您需要处理与自身进行比较的元素的情况。

虽然它没有严格保证,但我很确定List的Sort方法永远不会调用你的compare方法来比较一个对象与它自己,除非该对象碰巧多次出现在列表中。 我的结论是基于List.Sort是使用QuickSort算法(根据MSDN)实现的,这种算法从不进行比较, 通常不涉及将相同的元素与自身进行比较 (也没有任何其他记录的排序算法我能想到的的)。 (编辑:似乎微软的实现确实将元素与自身进行了比较。请参阅上面接受的答案。)

但是,良好的编码实践将指示您的IComparer实现应该能够处理在两个参数中传递相同的对象,否则您的实现不会完全填充IComparer定义的协定。 它可能适用于您的场景,但您将依赖于排序方法的实现细节(将来可能会更改),并且您将无法在其他没有此类情况的情况下使用IComparer实现。保证(或者更糟糕的是,您或其他人使用它并可能创建一个难以发现的错误)。

另一个答案,这个基于ECMA-335的XML部分, BCL(基类库)的规范。 虽然不能保证与实际实现有什么关系,但这是有权威的。 规范只说:

最坏的情况是,此操作为O(n ^ 2),其中n是要排序的元素数。 平均而言,它是O(n log n)。

虽然这是QuickSort的暗示,但绝对不能保证。 规范也不需要在Array.Sort方面实现。

底线:就规范而言,将项目与自身进行比较是完全可以的。