5

Consider the following code:

namespace ConsoleApplication1 {
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(100.CompareTo(200)); // prints -1
            Console.WriteLine(((decimal)100).CompareTo((decimal)200)); // prints -1
            Console.WriteLine(((short)100).CompareTo((short)200)); // prints -100
            Console.WriteLine(((float)100).CompareTo((float)200)); // prints -1
            Console.ReadKey();
        }
    } 
}

My question is, are there any specific reasons the CompareTo-method on Int16 returns values other than -1, 0 and 1?

ILSpy shows it is implemented this way

public int CompareTo(short value)
{
    return (int)(this - value);
}

whereas the method is implented on Int32 this way

public int CompareTo(int value)
{
    if (this < value)
    {
        return -1;
    }
    if (this > value)
    {
        return 1;
    }
    return 0;
}
sloth
  • 91,747
  • 17
  • 156
  • 204

2 Answers2

13

The difference is that for short, there's no chance of the result overflowing. For instance, short.MinValue - (short) 1 is still negative - whereas int.MinValue - 1 is int.MaxValue.

In other words, the specific reason is that you can get away with a shortcut with short (no pun intended) whereas the same shortcut doesn't work with int. You should definitely not require IComparable<T>.CompareTo implementations to return -1, 0 or 1. The documentation is pretty clear that the result is only meaningful in terms of being negative, zero, or positive.

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • 1
    Thanks for your answer. Didn't thought about the overflow issue. Unfortunately, I have to maintain a legacy application which contains a lot of code assuming CompareTo returns always -1, 0 or 1... – sloth Jul 05 '11 at 09:12
  • 1
    @dkson: I suggest you fix the legacy code. That sort of assumption will simply keep biting you until you eventually fix it. Better to do it sooner rather than later - and educate the original developers, if they're still around... – Jon Skeet Jul 05 '11 at 09:15
5

Well, you should only really check the sign anyway, but for reasons: I guess for int etc there would be a risk of overflow/wrap (when handling 2 large-magnitude numbers) that would reverse the sign, meaning it must check the operators.

I'd rather it was consistent, but it doesn't seem to be a problem. More likely an optimisation that is atypical but within the documented API. In particular, optimising short here doesn't feel like it is going to get a massive amount of use (I use short, but not anything like as much as I do int).

Marc Gravell
  • 927,783
  • 236
  • 2,422
  • 2,784