A Mixin for IComparable<T>
Following on from my other posts on C# Mixins, here’s a short one to demonstrate the benefits of Mixins using IComparable<T>.
I don’t know about you, but I can never remember how the CompareTo method of IComparable<T> works. If I remember correctly, it gives back -1 if the value of the compared object is less than the value of the called object, and +1 if the compared object is greater than the value of the called object.
No, wait! That’s the wrong way round! See what I mean?
The CompareTo method is defined like this:
int CompareTo(T other)
According to the MSDN Library, the value it returns is:
| Value | Meaning |
| Less than zero | This object is less than the other parameter. |
| Zero | This object is equal to other. |
| Greater than zero | This object is greater than other. |
Now I don’t know about you, but I always have trouble with that. Mix-ins to the rescue!
What I really need is to define my own methods on the IComparable<T> interface. Something like LessThan, MoreThan and ValueEquals. That would be much more valuable. I could define those methods in a superclass, and have my new classes all inherit from that superclass. But that would bind me to a certain structure, reduce the coherency of my classes, and make me feel bad. But if I implement IComparable<T> with its sole method, I can use a Mixin to take advantage of that method and add the new functionality I need, without affecting the structure of my code.
Here’s an example using the Temperature class shamelessly lifted from the MSDN Library.
The class Temperature is defined as:
public class Temperature : IComparable<Temperature> { // Implement the CompareTo method. For the parameter type, Use // the type specified for the type parameter of the generic // IComparable interface. // public int CompareTo(Temperature other) { // The temperature comparison depends on the comparison of the // the underlying Double values. Because the CompareTo method is // strongly typed, it is not necessary to test for the correct // object type. return m_value.CompareTo(other.m_value); } // The underlying temperature value. protected double m_value = 0.0; public Temperature(double degreesKelvin) { this.Kelvin = degreesKelvin; } }
Note that Temperature implements IComparable<Temperature>.
So now if you define a static extension class for IComparable<T>, you should also be able to use it with IComparable<Temperature>.
Here are the extension methods I’m going to add – LessThan, MoreThan, and ValueEquals:
public static class IComparableExtensions { public static bool LessThan<T>(this IComparable<T> comparable, T other) { return comparable.CompareTo(other) < 0; } public static bool MoreThan<T>(this IComparable<T> comparable, T other) { return comparable.CompareTo(other) > 0; } public static bool ValueEquals<T>(this IComparable<T> comparable, T other) { return comparable.CompareTo(other) == 0; } }
My program now references the IComparableExtensions class by importing its namespace. I then write:
var t1 = new Temperature(273); var t2 = new Temperature(100);
All I had to do was implement IComparable<T> with its one CompareTo method (which was trivial), and I automatically get the extension methods LessThan, MoreThan and ValueEquals mixed-in to my Temperature class.
if (t1.LessThan(t2)) Console.WriteLine("t1 is less than t2"); else if (t1.MoreThan(t2)) Console.WriteLine("t1 is more than t2");
And this doesn’t just work with IComparable<Temperature>, it works with anything which implements IComparable<T>. Classes implementing IComparable<int> would also get access to the new methods, for example.
Here’s the output of the code:
t1 is more than t2
… as you would expect.
And voila! That’s why mix-ins can be so useful.
I’ve intentionally done this example using a well-known interface, to make it easier to understand. But imagine what you could do by inheriting from a particular class of your own, defining your own interface, and then adding in more functionality using a mixin. You’ve nearly got multiple inheritance.
More to come on this…
This is my personal blog, where I express my thoughts and thinking about programming and software development.