Tigraine

Daniel Hoelbling-Inzko talks about programming

Reversing Comparers in .NET

Posted by Daniel Hölbling on April 4, 2009

Since LinQ stepped onto the stage I rarely think about sorting, selecting etc any more. A simple IEnumerable<T>.OrderBy(p => p.Id) does the trick quite nicely.

But, there are cases where I wanted the list to be sorted in itself, and so I turned to the SortedList and SortedDictionary classes in the System.Collections.Generic namespace.

Usage is incredibly easy, they are just ordinary IDictionary<Tkey, Tvalue> implementations that behave in every way as expected (no duplicate keys mind you), but in order to use them effectively you should be aware of some minor things about comparers.

Internally both collections will use a TreeSet structure that sorts itself by using a given IComparer<TKey> to determine their sort order. So all we need to do is add some pixie dust as the IComparer<TKey> to interfere with the order.

And since I don’t want to write one IComparer<T> for every type in the framework, I did a find-inheritor search with Reflector on the IComparer<TKey> interface only to discover that there is only one implementation: StringComparer. All other types get compared either by a custom comparer or the following call:

Comparer<TKey>.Default;

The static method Default will return an appropriate comparer for the given TKey type (taken from the IComparable<T> interface that has to be implemented by TKey).

So, in order to reverse the list, we just have to supply a custom comparer that reverses the default comparer.  (Since the LinQ .Reverse() method is out of the question :)).

And that’s rather easy once you know where to get the default comparer from:

public class ReverseComparer<T> : IComparer<T> where T : IComparable<T>
{
    private readonly IComparer<T> comparer;

    public ReverseComparer() : this(Comparer<T>.Default)     {     }

    public ReverseComparer(IComparer<T> comparerToReverse)     {         comparer = comparerToReverse;     }

    public int Compare(T x, T y)     {         return comparer.Compare(y, x);     } }

This generic class will reverse any given comparer type (you can even supply your own IComparer<T> to get reversed).

I am not perfectly sure why this isn’t in the framework, maybe I just overlooked it or there are other ways to reverse a list. But for the moment this works just fine.

Filed under net, programmierung
comments powered by Disqus

My Photography business

Projects

dynamic css for .NET

Archives

more