Because the SByte.CompareTo()
is implemented like
return m_value - value;
so a simple subtraction. This works because the m_value
is converted automatically to int
, and any possibile combination of values is "legal" with int
.
With two Int32
this can't be done, because for example Int32.MinValue.CompareTo(Int32.MaxValue)
would become Int32.MinValue - Int32.MaxValue
that would be outside the int
range, and in fact it is implemented as two comparisons:
if (m_value < value) return -1;
if (m_value > value) return 1;
return 0;
in general
The only important "thing" of the returned value of a CompareTo
is its sign (or if it is 0). The "value" is irrelevant. The return value of 1, 5, 500, 5000, 5000000 of CompareTo()
are the same. CompareTo
can't be used to measure "distance" between numbers. So both implementations are equivalent.
It is totally wrong to do:
if (someValue.CompareTo(someOtherValue) == -1)
you must always
if (someValue.CompareTo(someOtherValue) < 0)
why the SByte.CompareTo
is built that way
SByte.CompareTo
is implementing a "branchless" comparison (there are no if
s in the code, the flow of code is linear). Processors have problems with branches, so branchless code could be faster than "branchful" code, so this microoptimization. Clearly SByte.CompareTo
could have been written as Int32.CompareTo
.
why any negative value is equivalent to -1 (and any positive value is equivalent to +1)
This is probably something that is derived directly from the C language: the qsort function for example to compare items uses a user-defined method that is like:
Pointer to a function that compares two elements.
This function is called repeatedly by qsort to compare two elements. It shall follow the following prototype:
int compar (const void* p1, const void* p2);
Taking two pointers as arguments (both converted to const void*). The function defines the order of the elements by returning (in a stable and transitive manner):
return value meaning
<0 The element pointed to by p1 goes before the element pointed to by p2
0 The element pointed to by p1 is equivalent to the element pointed to by p2
>0 The element pointed to by p1 goes after the element pointed to by p2
how is the .CompareTo
implemented in other primitive types?
SByte
, Byte
, Int16
, UInt16
, Char
all use the subtraction "method", while Int32
, UInt32
, Int64
, UInt64
all use the if
"method".
SByte - SByte
can not overflowInt32
, butInt32 - Int32
can.IComparable
interface is defined as having to return a value > 0, 0 or < 0. It does not specify which values these have to be exactly. Most people use1
,0
and-1
but any other value is perfectly allowed as well. The only thing that matters are the signs for > and < and 0 for equal.IComparable
orIComparable<T>
are used for ordering, so it's only important to know whether two objects are equal(zero), one is less- or greater than zero. What value is returned depends on the implementation and is irrelevant.