posted on Tuesday, October 11, 2005 8:09 AM by anoras

C# 3.0 and the Spaceship Operator

Abhinaba has an interesting blog entry about my all time favorite operator; Ruby’s spaceship operator <=>. This operator is a comparison operator akin to .NET IComparable interface. A part from looking cool in the editor, the operator it self isn’t the reason for my interest in it. It is the power of combining the spaceship operator with Ruby’s Comparable which’s shows the true power of mixins. If a Ruby class implements the spaceship operator, you get the <, <=, ==, >= and > operators, as well as a between? method for free just by importing the Comparable mixin.
Abhinaba points out how much simpler operator overloading would be if C# supported the spaceship operator. I agree with him on this, but with C# 3.0 we'recloser to encounters of the third kind than you might think. Regular readers of my blog might recall my post on Ruby mixins and C# 3.0 extension methods from last month. In that post I point out that extension methods resemble mixins, and since the spaceship operators true power comes from Ruby’s Comparable mixin this is a great opportunity to showcase the power of C# 3.0 extension methods.
We’ll use the IComparable<> and IComparable interfaces as a replacement for the spaceship, and since you cannot overload operators in an extension method, we’ll have to resort to named methods for the comparisons. A part from that we can get the whole shebang, including the Rubyesque between operator.

I’ve used the same Employee class as Abhinaba for my example, with the IComparable interfaces implemented.
class Employee : IComparable<Employee>, IComparable
{
    public Employee(string name, int jobGrade)
    {
        Name = name;
        JobGrade = jobGrade;
    }
    public string Name;
    public int JobGrade;

    public int CompareTo(Employee obj)
    {
        if (this.JobGrade
        else if(this.JobGrade==obj.JobGrade) return 0;
        else if (this.JobGrade>obj.JobGrade) return 1;
        return 0;
    }
    public int CompareTo(object obj)
    {
        Employee objAsEmployee=obj as Employee;
        if (objAsEmployee==null)
        {
            throw new ArgumentException("The parameter must be an Employee","obj");
        }
        return CompareTo(objAsEmployee);
    }
}

The client code is a no brainer. It just calls the extension methods on instances of the Employee class. The extension methods are mixed into the Employee implementation because I’ve added a using ComparableExtension directive to the application.
Employee employee1=new Employee("Arthur Dent",42);
Employee employee2=new Employee("Ford Prefect",10);
Employee employee3=new Employee("Trillian",15);
// Prints False
Console.WriteLine(employee1.LessThan(employee2));
// Prints True
Console.WriteLine(employee2.LessThanOrEqual(employee1));
// Prints True
Console.WriteLine(employee3.Between(employee1,employee3));

The interesting part is the implementation of the extension methods.
public static class ComparableExension
{
    public static bool GreaterThan(this object obj, object other)
    {
        return ((IComparable)obj).CompareTo(other)>0;
    }
    public static bool GreaterThanOrEqual(this object obj, object other)
    {
        return ((IComparable)obj).CompareTo(other)>=0;
    }
    public static bool EqualTo(this object obj, object other)
    {
        return ((IComparable)obj).CompareTo(other)==0;
    }
    public static bool LessThan(this object obj, object other)
    {
        return ((IComparable)obj).CompareTo(other)<0;
    }
    public static bool LessThanOrEqual(this object obj, object other)
    {
        return ((IComparable)obj).CompareTo(other)<=0;
    }
    public static bool Between(this object obj, object min, object max)
    {
        return (GreaterThanOrEqual(obj,min) && LessThanOrEqual(obj,max)) || (LessThanOrEqual(obj,min) && GreaterThanOrEqual(obj,max));
    }
}
As you can see from the code snippet above, this class is also fairly straight forward. The various comparison methods just use the IComparable interface on the objects to compare to determine whether they’re less than, equal to or greater than each other.

Comments

# re: C# 3.0 and the Spaceship Operator @ Saturday, July 28, 2007 1:15 PM

Nice solution, but the usage will not be really elegant. It looks like the problem is not the absence of the spaceship operator. If you could overload operators in an extension module then all comparison operators could easily be added to a class in the way you scetched in your example above.
It might be a good idea to have the IComparable Interface include all comparison operators then. Wouldn't it be nice if any class which implements IComparable had all comparison operators available and you could rely on the fact that
a>b means a.CompareTo(b)>0.
I don't know why Microsoft didn't allow operator overloading in extension methods, but for sure they really gave away half of the benefit of extension methods by doing this.

Boris

# re: C# 3.0 and the Spaceship Operator @ Friday, October 19, 2007 2:39 AM

Nice...

Theodosios

# re: C# 3.0 and the Spaceship Operator @ Friday, October 19, 2007 10:06 AM

Nice...

Polyvios

# re: C# 3.0 and the Spaceship Operator @ Friday, October 19, 2007 5:01 PM

Cool!

Augustinos

# re: C# 3.0 and the Spaceship Operator @ Saturday, October 20, 2007 5:38 AM

Cool!

Lambro

# re: C# 3.0 and the Spaceship Operator @ Saturday, October 20, 2007 6:39 AM

Cool.

Stavros

# re: C# 3.0 and the Spaceship Operator @ Saturday, October 20, 2007 11:10 AM

Sorry :(

Athanasios

# re: C# 3.0 and the Spaceship Operator @ Saturday, October 20, 2007 11:47 AM

Cool.

Loukianos

# re: C# 3.0 and the Spaceship Operator @ Sunday, October 21, 2007 2:58 AM

Interesting...

Christoforos

# re: C# 3.0 and the Spaceship Operator @ Sunday, October 21, 2007 7:47 PM

Cool!

Panos

# re: C# 3.0 and the Spaceship Operator @ Thursday, November 01, 2007 12:58 PM

Nice!

Thanasis

# re: C# 3.0 and the Spaceship Operator @ Thursday, November 01, 2007 5:34 PM

Nice!

Zeus

# re: C# 3.0 and the Spaceship Operator @ Thursday, November 01, 2007 5:44 PM

Sorry :(

Zeus

# re: C# 3.0 and the Spaceship Operator @ Friday, November 02, 2007 12:45 AM

Nice

Lambro

# re: C# 3.0 and the Spaceship Operator @ Friday, November 02, 2007 1:00 AM

Sorry :(

Andreas

# re: C# 3.0 and the Spaceship Operator @ Friday, November 02, 2007 4:50 PM

Nice!

Laurentios

# re: C# 3.0 and the Spaceship Operator @ Friday, November 02, 2007 5:28 PM

Cool.

Iannis

# re: C# 3.0 and the Spaceship Operator @ Saturday, November 03, 2007 12:00 AM

Cool.

Theodosios

# re: C# 3.0 and the Spaceship Operator @ Saturday, November 03, 2007 3:07 AM

Cool!

Aineias

# re: C# 3.0 and the Spaceship Operator @ Saturday, November 03, 2007 4:09 AM

Nice...

Zeus

# re: C# 3.0 and the Spaceship Operator @ Saturday, November 03, 2007 9:45 AM

Cool.

Aleksiu

# re: C# 3.0 and the Spaceship Operator @ Saturday, November 03, 2007 9:49 AM

Nice...

Odysseus

# re: C# 3.0 and the Spaceship Operator @ Sunday, November 04, 2007 9:19 AM

Interesting...

Ivan

# re: C# 3.0 and the Spaceship Operator @ Sunday, November 04, 2007 8:42 PM

Nice

Tasos

# re: C# 3.0 and the Spaceship Operator @ Sunday, November 04, 2007 10:31 PM

Sorry :(

Carolos

# re: C# 3.0 and the Spaceship Operator @ Sunday, November 04, 2007 11:54 PM

interesting

Panagiote

# re: C# 3.0 and the Spaceship Operator @ Monday, November 05, 2007 1:11 AM

Cool...

Kalinikos

# re: C# 3.0 and the Spaceship Operator @ Monday, November 05, 2007 11:33 AM

interesting

Georges

# re: C# 3.0 and the Spaceship Operator @ Monday, November 05, 2007 1:45 PM

Cool!

Antonis

# re: C# 3.0 and the Spaceship Operator @ Tuesday, November 06, 2007 12:47 AM

Nice...

Thanasios

# re: C# 3.0 and the Spaceship Operator @ Tuesday, November 06, 2007 2:00 AM

Nice

Angelos

# re: C# 3.0 and the Spaceship Operator @ Tuesday, November 06, 2007 9:14 AM

Sorry :(

Odysseus

# re: C# 3.0 and the Spaceship Operator @ Tuesday, November 06, 2007 10:29 AM

Nice!

Antonis

# re: C# 3.0 and the Spaceship Operator @ Tuesday, November 06, 2007 12:32 PM

Nice...

Andonios

# re: C# 3.0 and the Spaceship Operator @ Tuesday, November 06, 2007 10:55 PM

Interesting...

Dino

# re: C# 3.0 and the Spaceship Operator @ Wednesday, November 07, 2007 1:46 AM

Nice

Nick

# re: C# 3.0 and the Spaceship Operator @ Wednesday, November 07, 2007 10:15 AM

Nice

Miltos

# re: C# 3.0 and the Spaceship Operator @ Wednesday, November 07, 2007 4:01 PM

Cool.

Anastasios

# re: C# 3.0 and the Spaceship Operator @ Wednesday, November 07, 2007 5:07 PM

Nice...

Georgios

# re: C# 3.0 and the Spaceship Operator @ Thursday, November 08, 2007 2:34 AM

Interesting...

Iason

# re: C# 3.0 and the Spaceship Operator @ Thursday, November 08, 2007 2:37 AM

Cool...

Romanos

# re: C# 3.0 and the Spaceship Operator @ Thursday, November 08, 2007 3:41 AM

Interesting...

Dionysios

# re: C# 3.0 and the Spaceship Operator @ Thursday, November 08, 2007 9:14 AM

Nice...

Tzannas