Let's say I have a type that implements IComparable.
I would have thought it's reasonable to expect that the operators ==
, !=
, >
, <
, >=
and <=
would "just work" automatically by calling CompareTo but instead I have to override them all if I want to use them.
From the language design perspective is there a good reason it was done this way? Are there any cases when you it's genuinely useful for A>B
to behave differently to Compare(A,B)>0
?
Operator overloading is a crucial concept in C++ that lets you achieve the functionality of the built-in operators while working with user-defined data types. Comparison operators in C++ are the ones that are there to compare two values with each other such as “==”, “!=
When you provide an implementation of IComparable, you must usually also override Equals so that it returns values that are consistent with CompareTo. If you override Equals and are coding in a language that supports operator overloads, you should also provide operators that are consistent with Equals.
Operator Overloading in Binary Operators Here, + is a binary operator that works on the operands num and 9 . When we overload the binary operator for user-defined types by using the code: obj3 = obj1 + obj2; The operator function is called using the obj1 object and obj2 is passed as an argument to the function.
An overloaded operator is called an operator function. You declare an operator function with the keyword operator preceding the operator. Overloaded operators are distinct from overloaded functions, but like overloaded functions, they are distinguished by the number and types of operands used with the operator.
The whole situation is vexing. C# has too many ways to express equality and inequality:
They all have subtly different semantics and with the exception of static Equals, none automatically uses the other, and none actually has the behavior that I want. Static methods are dispatched based on the compile-time type of both operands; the virtual methods / interface methods are dispatched based on the run-time type of one of the operands, which makes the operation asymmetric; the type of one side matters more than the type of the other.
I can't imagine that anyone thinks that the situation we're in is great; given no constraints, this is not what would have evolved. But managed language designers do have constraints: the CLR does not implement static methods in interface contracts or double-virtual dispatch, or the ability to put an operator constraint on a generic type parameter. And therefore multiple solutions have evolved to solve the equality/inequality problem.
I think that were the CLR and C# designers to go back in time and tell their past selves what features ought to be in v1 of the CLR, some form of static methods in interfaces would be high on the list. If there were static methods in interface then we can define:
interface IComparable<in T, in U> { static bool operator <(T t, U u); static bool operator >(T t, U u); ... etc
And then if you have:
static void Sort<T>(T[] array) where T : IComparable<T, T>
You could then use the <
and ==
and so on operators to compare elements.
Two main reasons:
Update as per Eric Lippert among others, the following is the appropriate standard implementation of the comparison operators in C# for a type UDT:
public int CompareTo(UDT x) { return CompareTo(this, x); } public bool Equals(UDT x) { return CompareTo(this, x) == 0; } public static bool operator < (UDT x, UDT y) { return CompareTo(x, y) < 0; } public static bool operator > (UDT x, UDT y) { return CompareTo(x, y) > 0; } public static bool operator <= (UDT x, UDT y) { return CompareTo(x, y) <= 0; } public static bool operator >= (UDT x, UDT y) { return CompareTo(x, y) >= 0; } public static bool operator == (UDT x, UDT y) { return CompareTo(x, y) == 0; } public static bool operator != (UDT x, UDT y) { return CompareTo(x, y) != 0; } public override bool Equals(object obj) { return (obj is UDT) && (CompareTo(this, (UDT)obj) == 0); }
Just add the custom definition for private static int CompareTo(UDT x, UDT y)
and stir.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With