2

I want to sort a list with the help of IComparable<T>.CompareTo for a type T called Path. I wrote

var shortest = new List<Path>();
//Fill shortest with elements != null
if (shortest.Contains(null))
      throw new System.Exception("Path is null");
shortest.Sort();
if (shortest.Contains(null))
      throw new System.Exception("Path is null");

To my surprise, the method

    int IComparable<Path>.CompareTo(Path other)
    {
        if (other == null)
            return -1;

        if (!other.valid)
            return 1;

        if (pfad.Count() > other.pfad.Count())
        {
            return -1;
        }
        else if (pfad.Count() < other.pfad.Count())
        {
            return 1;
        }
        else
        {
            if (length > other.length)
                return -1;
            else
                return 1;

        }

    }

from the class

 public class Path : IComparable<Path>

is called from Sort() with other==null. I am even more surprised that in the first code-block, the second exception is thrown, meaning that shortest contains a null value after the sort and not before.

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
  • Do you have a custom equality comparer? Does your list of paths contain a null value? – JMan Jan 28 '13 at 14:50
  • there is a similar question on SO.. http://stackoverflow.com/questions/6189750/sorting-icomparable-objects-some-of-which-are-null – Amitd Jan 28 '13 at 14:52
  • I do not see the similarity. My question is: Why does Sort compare some value to null if my list never contains the value null? – J Fabian Meier Jan 28 '13 at 14:58
  • Are you asking why `IComparable` needs to be able to compare to `null` or why your code seems to be sorting a list that contains a `null` item when it should be throwing an exception? – D Stanley Jan 28 '13 at 15:00
  • The second thing: If the list does not contain null, why does Sort() call CompareTo with other==null ? – J Fabian Meier Jan 28 '13 at 15:01
  • How do you know that the CompareTo comparing with null is from the `Sort` and not from the `Contains`? – Servy Jan 28 '13 at 15:04
  • Does Path implement `IEquatable` and/or `IComparable`? If so, please add the implementation(s) to your question. – D Stanley Jan 28 '13 at 15:06
  • @Servy would `Contains` call `IComparable.CompareTo`? I think it just calls `IEquatable.Equals`. – D Stanley Jan 28 '13 at 15:07
  • I added some code to make the situation clearer – J Fabian Meier Jan 28 '13 at 15:13
  • @DStanley This seems to be demonstrating that it's using `CompareTo`. – Servy Jan 28 '13 at 15:16

2 Answers2

1

While I cannot explain why Sort needs to compare to null, the documentation of IComparable.CompareTo explicitly states:

By definition, any object compares greater than (or follows) null, and two null references compare equal to each other.

As such, whatever the reason is, the implementation of CompareTo has to follow this and the other rules to ensure compatibility with Sort() et al.

BambooleanLogic
  • 7,530
  • 3
  • 30
  • 56
  • `"the implementation of CompareTo has to follow this"`, well, no, it doesn't. Nothing prevents you from violating that; it's just a convention, not a requirement (and a rather poor convention at that). – Servy Jan 28 '13 at 15:03
  • Except library methods that use CompareTo often assume that they follow these conventions and may therefore behave unexpectedly if such is not the case. As such, you don't _have to_ follow them per se, but not doing so may lead to issues with said methods. – BambooleanLogic Jan 28 '13 at 15:07
  • I've never come across a problem as a result of this. There may be certain implementations of say, sort, or whatever other algorithm using comparisons, that may not call `CompareTo` at all on null values, and instead assume that null is "first", in which case it wouldn't *matter* what your solution did. If they don't, then it will work just fine. – Servy Jan 28 '13 at 15:16
1

Your CompareTo function is broken. It doesn't return 0 when an object is compared to itself and it always returns 1 when two objects with valid == false are compared. So there might be two objectsa and b with a.CompareTo(b) == 1 and b.CompareTo(a) == 1 and this might lead to Sort() behave strangely.

Also, as already noted in the other answer, it should return 1 if other == null. (shouldn't really matter when the list doesen't contain null)

Henrik
  • 23,186
  • 6
  • 42
  • 92
  • You're right. I still do not understand the behaviour of the sort function, but if I rewrite it using Sort(Comparison), it works. – J Fabian Meier Jan 28 '13 at 15:43