Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In the List<T>.Sort() method, is an item ever compared to itself?

If I pass in a custom IComparer to an instance of a List's Sort() method, will the comparer's Compare(x,y) method ever be called with the same item?

ie. Is it possible that Compare(x,x) may be called.

Edit: More interested in the case where items of the list are distinct.

like image 267
ForeverLearnNeverMaster Avatar asked Sep 10 '11 18:09

ForeverLearnNeverMaster


3 Answers

I wrote a test program to try it out. It looks like it actually does Compare() the same element to itself (at least Compare() is called for the same item twice). In this program, Compare() is called with arguments (2, 2).

using System;
using System.Collections.Generic;

static class Program
{
    class MyComparer : Comparer<int>
    {
        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<int> list = new List<int> { 1, 2, 3 };
        list.Sort(comparer);
        return;

    }
}

And the output is:

Compare(1, 2)
Compare(1, 3)
Compare(2, 3)
Compare(1, 2)
Compare(2, 2)
Compare(2, 3)
Compare(2, 2)
like image 98
JohnD Avatar answered Nov 08 '22 10:11

JohnD


Another answer, this one based on the XML part of ECMA-335, the specification of the BCL (Base Class Library). Although not guaranteed to relate to what actual implementations do, this is as authoritative as it gets. And the spec states nothing but:

At worst, this operation is O(n^2), where n is the number of elements to sort. On average it's O(n log n).

Though this is suggestive of QuickSort, it is absolutely no guarantee. Nor does the spec require implementation in terms of Array.Sort.

Bottom line: as far as the spec is concerned, it is perfectly okay for implementations to compare items to themselves.

like image 29
Thomas Avatar answered Nov 08 '22 09:11

Thomas


Although it's not strictly guaranteed, I'm pretty sure List's Sort method will never call your compare method to compare an object to itself unless that object happens to appear in the list multiple times. I base this conclusion on the fact that List.Sort is implemented using the QuickSort algorithm (according to MSDN), which never compares usually does not involve comparing the same element to itself (and neither do any of the othe documented sorting algorithms I can think of). (Edit: It seems that Microsoft's implementation does compare the element to itself. See accepted answer above.)

However, good coding practice would dictate that your IComparer implementation should be able to handle being passed the same object in both parameters, as otherwise your implementation is not fullfilling the contract defined by IComparer. It would probably work for your scenario, but you'd be relying on implementation details of the sort method (which might change in the future), and you wouldn't be able to use you IComparer implementation in other scenarios where there is no such guarantee (or worse, you or someone else DOES use it and possibly creates a difficult to find bug).

like image 2
Nimrand Avatar answered Nov 08 '22 10:11

Nimrand