Yet another use for Extension methods : Extending IComparable<T>

I keep finding more uses for extension methods. This time it's extending IComparable<T>. The API signature for IComparable<T> has been around since the dawn of C: if the left is less than the right, return something less than 0, if left is greater than right, return something greater than 0, and if they are equivalent, return 0. Well, its readability leaves a bit to be desired.

So I wrote this set of extension methods for any type T that implements IComparable<T>:

public static class EquatableExtensions
{
    public static bool GreaterThan<T>(this T left, T right) where T : IComparable<T>
    {
        return left.CompareTo(right) > 0;
    }

    public static bool LessThan<T>(this T left, T right) where T : IComparable<T>
    {
        return left.CompareTo(right) < 0;
    }

    public static bool GreaterThanOrEqual<T>(this T left, T right) where T : IComparable<T>
    {
        return left.CompareTo(right) >= 0;
    }

    public static bool LessThanOrEqual<T>(this T left, T right) where T : IComparable<T>
    {
        return left.CompareTo(right) <= 0;
    }

    public static bool Equal<T>(this T left, T right) where T : IComparable<T>
    {
        return left.CompareTo(right) == 0;
    }
}

These methods mean I can write this:

if (foo.GreaterThan(bar))

instead of

if (foo.CompareTo(bar) > 0)

personally, I find the former much easier to read.

Ok, this is not rocket science, but it's useful, and it improves the readability of quite a bit of the code I work with on a day to day basis.

Published 07 January 2008 09:19 AM by wwagner

Comments

# Koen said on 08 January, 2008 04:08 AM

Don't you have to provide the generic type when you use it as an extension method?

In your example you use:

if (foo.GreaterThan(bar))

instead of

if (foo.GreaterThan<SomeType>(bar))

# Peter Ritchie said on 08 January, 2008 11:20 AM

And for those not familiar with all the nuances of generics and IComparable<T>, this doesn't mean you can do this:

Int16 left = 10;

Int32 right = 2;

Trace.WriteLine(left.GreaterThan(right));

...which is a good thing; but is slightly different than not using these extension methods:

Int16 left = 10;

Int32 right = 2;

Trace.WriteLine(left.CompareTo(right) > 0);

...which compiles without error--only to result in a runtime error when executed.  This results in a call to IComparable.CompareTo(object); but many IComparable implementations don't support comparison to many other types (plus it would incur some boxing).  

BTW, "dawn of C(colon)"?

# a salmon of doubt » CodeMash Day 2 Not-So-Mega-Summary said on 11 January, 2008 09:50 PM

Pingback from  a salmon of doubt &raquo; CodeMash Day 2 Not-So-Mega-Summary

# wwagner said on 17 January, 2008 06:52 AM

Koen,

When a generic method's parameters can be inferrd, you don't need the angle brackets.

if (foo.GreaterThan(bar)) compiles just fine.

The compiler knows that foo is <SomeType> and generates the write method call.

Search

Go

Blog Group Links

Nascar style badges