Operator Overloading Stupidity

I’m back in .NET land after living, pretty much exclusively, for the last two years in Java-and-Ruby land and while I generally like C#, I ran across something today that is really stupid. It involves operator overloading. While I actually like operator overloading and think it can be a powerful thing, the implementation of one facet of it in C# is just wrong. The problem is that they force you to override certain operators in pairs instead of defining them in terms of each other or in terms of a single method. In other words, if I define == to check equality then I also have to define != to check inequality! Why in the world should I have to do that since inequality is the opposite of equality and can be defined in terms of the equality operator? The same holds true for < & > and <= & >=. What you end up with is something like this:

   1  public class Foo   2  {   3      private int val;   4   5      public Foo(int val)   6      {   7          this.val = val;   8      }   9  10      public static bool operator==(Foo lhs, Foo rhs)  11      {  12          return lhs.val == rhs.val;  13      }  14  15      public static bool operator!=(Foo lhs, Foo rhs)  16      {  17          return ! (lhs == rhs);  18      }  19  }  

where the != operator just negates a call to ==. You would repeat this process for the other two pairs if you wanted to provide them. (And yes, I know if you provide your own == then you have to also provide a GetHashCode method.) There is no reason that the developer should have to do anything more than provide a comparison operator and then let the system define the other methods in terms of that comparison…

And that’s exactly what Ruby does. If you include the module called “Comparable” in your class, and provide a comparison method called (called the “spaceship method” because that’s what it looks like) then you get ==, !=, <, and >= for free! That’s right, by defining one method you get six defined in terms of it automatically. Now that’s how it should be done! Which results in code like this:

   1  class Foo   2      include Comparable  # Here's where the majic starts   3   4      attr_accessor :val   5   6      def initialize(val)   7          self.val = val   8      end   9  10      # comparison method; all others defined in terms of this  11      def (other)  12          val  other.val  13      end  14  end  

Obviously these are both trivial classes but I think you get the point. There is no reason why you should have to define more than one method to get all the normal comparisons that you would expect in a language.

Advertisements

One thought on “Operator Overloading Stupidity

Comments are closed.