Adsense

Tuesday, May 27, 2008

How to Sort a generic IList or List

A while back I wrote a post on How to sort a Generic IList. Here is another approach.
To sort a generic List<T>, you can create a class that implements IComparer<T> and tells the list how to sort itself. Its fairly straight forward and the example below shows how to sort Widgets.
A Widget is a simple class that has a public string Name and a public int Size. I want to be able to sort generic lists of widgets (List<Widget>) by name and by size. You can see my code below.
The widget and sorter implementations
public class Widget {
    public string Name = string.Empty;
    public int Size = 0;

    public Widget(string name, int size) {
this.Name = name;
this.Size = size;
}
}

public class WidgetNameSorter : IComparer<Widget> {
    public int Compare(Widget x, Widget y) {
        return x.Name.CompareTo(y.Name);
}
}

public class WidgetSizeSorter : IComparer<Widget> {
    public int Compare(Widget x, Widget y) {
return x.Size.CompareTo(y.Size);
}
}
And application to create the list and sort it
class Program {
static void Main(string[] args) {
List<Widget> widgets = new List<Widget>();
widgets.Add(new Widget("Zeta", 6));
widgets.Add(new Widget("Beta", 3));
widgets.Add(new Widget("Alpha", 9));

OutputWidgets(widgets);
widgets.Sort(new WidgetNameSorter());
OutputWidgets(widgets);
widgets.Sort(new WidgetSizeSorter());
OutputWidgets(widgets);

Console.ReadLine();
}

public static void OutputWidgets(List<Widget> widgets) {
foreach (Widget w in widgets) {
Console.WriteLine(string.Format("{0} - {1}", w.Name, w.Size));
}
Console.WriteLine(string.Empty);
}
}
Running the application above results in the following output.
output
Straight forward enough? =)
So what do you do if you have a generic IList<T> and want to sort it? Since you only have the interface reference that can't make assumptions about what's implementing it, you have no Sort method. You can use the ToList() method to convert the IList<T> into a List<T>, and then call the Sort() method. See the updated example below. (Note: I previously blogged about a way to sort a generic IList using the ArrayList.Adapter. You can read about it HERE.)
class Program {
static void Main(string[] args) {
IList<Widget> widgets = new List<Widget>();

widgets.Add(new Widget("Zeta", 6));
widgets.Add(new Widget("Beta", 3));
widgets.Add(new Widget("Alpha", 9));

OutputWidgets(widgets);
widgets.ToList().Sort(new WidgetNameSorter());
OutputWidgets(widgets);
widgets.ToList().Sort(new WidgetSizeSorter());
OutputWidgets(widgets);

Console.ReadLine();
}

public static void OutputWidgets(IList<Widget> widgets) {
OutputWidgets(widgets.ToList());
}

public static void OutputWidgets(List<Widget> widgets) {
foreach (Widget w in widgets) {
Console.WriteLine(string.Format("{0} - {1}", w.Name, w.Size));
}
Console.WriteLine(string.Empty);
}
}