Friday, March 13, 2009

Implementing IComparer in C#

I was working on some extension methods today allowing me to pick an item out of an IList that best meets some criteria.

I started with just a delegate that takes two objects and returns a bool indicating that the first is a better fit than the second. I expanded the functionality to take an IComparer so that you can use the same comparison for the extension method that you use for sorting.

It was the first time I've written an IComparer so I thought I'd try a few techniques out. The first thing I wanted to do was to actually implement an IComparer (as opposed to just using the CompareTo method on the underlying comparison object). That is to say, I wanted to control returning -1, 0, or 1 myself. Here's what I came up with:
public class AgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
if (x.Age == y.Age) return 0;
return (x.Age > y.Age) ? 1 : -1;
}
}
It was pretty cool and it worked just fine. I needed another comparer that reversed directions so that I could sort in descending order. I tried 3 different ways (one way was to reverse the logic, but if the logic changed in one, it'd have to change in both and I didn't want that). One way to accomplish inverting the logic of an IComparer is to create an instance of the original comparer and reverse the parameters:
public class ReverseAgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
AgeComparer oc = new AgeComparer();
return oc.Compare(y, x);
}
}
The only downside to this method is that it sort of obfuscates what you're doing. I think negating the result of the original IComparer is a little clearer:
public class ReverseAgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
AgeComparer oc = new AgeComparer();
return oc.Compare(x, y) * -1;
}
}
With that in mind, I made the Compare method on the AgeComparer virtual and implemented my final attempt like this:
public class ReverseAgeComparer : AgeComparer
{
public override int Compare(Person x, Person y)
{
return base.Compare(x, y) * -1;
}
}

2 comments:

  1. Man it is hard trying to learn about these things by myself because 90% of the tutorials for this kinds of things out there assume you are programmer, the others try to teach newbies using all the terms and abreviation that one would expect a pro to know.

    Yours is no exception.

    Can't people just give streamlined, thorough easy to understand explanations and examples?

    ReplyDelete
  2. Fernando, thank you very much for your feedback. I'm sorry that my response is so late and I'm sorry this post didn't meet your needs. Please feel free to comment again and let me know what I can do to better explain what you needed. I'd be happy to add another IComparer tutorial to my blog.

    Sincerely,
    D. Patrick Caldwell

    ReplyDelete