IComparable implemented without comparison operators
ID |
vbnet.correctness.icomparable_needs_operators |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Type Design |
Language |
VB.NET |
Description
Reports a type that implements IComparable or IComparable(Of T) but declares none of the comparison operators <, >, ⇐ and >=. A comparable type that declares at least one of them is not reported, and neither is a type that only overloads = and <>, which express equality rather than ordering.
Rationale
Implementing IComparable states that instances of the type have a well-defined order, and CompareTo is what sorting, SortedList, SortedSet and LINQ’s OrderBy will call. Callers writing ordinary code, however, reach for a < b. Without the operators that expression does not compile, so every comparison at a call site has to be spelled a.CompareTo(b) < 0 - easy to get backwards, and easy to write inconsistently across a codebase. Worse, when the operators are added later by someone unaware of CompareTo, the two can disagree: a < b and a.CompareTo(b) < 0 then give different answers for the same pair, and which one runs depends on whether the call site is generic or concrete.
The following code illustrates the pattern detected by this rule:
Namespace Acme.Catalog
' FLAGGED: IComparable implemented without comparison operators
Public Structure PartNumber
Implements IComparable
Public Sequence As Integer
Public Function CompareTo(ByVal obj As Object) As Integer Implements IComparable.CompareTo
Return Sequence.CompareTo(DirectCast(obj, PartNumber).Sequence)
End Function
Remediation
Implement CompareTo once as the single definition of the order, then add Public Shared Operator <, >, ⇐ and >= as one-line delegations to it, for example Return a.CompareTo(b) < 0. Add the = and <> operators together with an Equals override in the same pass, so that equality and ordering agree on the boundary case where CompareTo returns zero.