-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Description
The documentation for IComparable<T> says, in part:
If you implement
IComparable<T>, you should overload theop_GreaterThan,op_GreaterThanOrEqual,op_LessThan, andop_LessThanOrEqualoperators to return values that are consistent withCompareTo(T)
And the documentation for CompareTo(T) in turn says, in part:
By definition, any object compares greater than null
The example given in the IComparable documentation is consistent with these two things:
public int CompareTo(Temperature other)
{
// If other is not a valid object reference, this instance is greater.
if (other == null) return 1;
// The temperature comparison depends on the comparison of
// the underlying Double values.
return m_value.CompareTo(other.m_value);
}
// Define the is greater than operator.
public static bool operator > (Temperature operand1, Temperature operand2)
{
return operand1.CompareTo(operand2) > 0;
}
However, these seem to contradict the documentation for compiler warning CS0464, which says, in part:
A comparison like i == null can be either true of false. A comparison like i > null is always false.
Side note: There's a little typo in that documentation, which maybe you'd want to fix - "true of false" rather than "true or false". Anyway:
I tried it out with a very common class (Int32) just to see what it does. At least for that class, for the > and >= operators:
- The ```CompareTo```` "any object compares greater than null" is correct, and
- The CS0464 "A comparison like i > null is always false", is correct, and
- Put those together and the
IComparer<T>"you should overload theop_GreaterThan,op_GreaterThanOrEqual,op_LessThan, andop_LessThanOrEqualoperators to return values that are consistent withCompareTo(T)" is necessarily broken.
I guess the word "should" in there doesn't imply "must", but... the whole IComparable/IEquatable/op_Whatever/GetHashCode/Equals<T>/Equals<Object>/Object.Equals/whatever-else-I-am-missing stuff is notoriously difficult, with lots of people confused over exactly what should be implemented and how, and this sure doesn't help.
Reproduction Steps
Note: > is demonstrated here, but >= behaves the same way:
Console.WriteLine($"nonnull > null: {new Int32() > null}");
Console.WriteLine($"nonnull.CompareTo(null) > 0: {(new Int32()).CompareTo(null) > 0}");
Expected behavior
LOL, I don't know. That's a big part of the problem. According to IComparable<T> and CompareTo<T> (i.e. "consistent operator/CompareTo behavior" plus "objects CompareTo greater than null"), it seems it should output:
nonnull > null: True
nonnull.CompareTo(null) > 0: True
Whereas according to CompareTo<T> and CS0464 (i.e., "objects CompareTo greater than null" plus "operators other than == and != are always false for null") it seems like it should output:
nonnull > null: False
nonnull.CompareTo(null) > 0: True
And according to IComparable<T> and CS0464 (i.e. ""consistent operator/CompareTo behavior" plus "operators other than == and != are always false for null"), it seems like it should be:
nonnull > null: False
nonnull.CompareTo(null) > 0: False
Actual behavior
At least in the case of Int32:
nonnull > null: False
nonnull.CompareTo(null) > 0: True
Regression?
No response
Known Workarounds
No response
Configuration
- version of .NET: 8.0
- OS and version: Windows 11
- architecture: x64
- specific to that configuration: I don't know. I doubt it.
- If you're using Blazor: I'm not.
Other information
No response