The trick is to implement a stable sort. I've created a Widget class that can contain your test data:
public class Widget : IComparable { int x; int y; public int X { get { return x; } set { x = value; } } public int Y { get { return y; } set { y = value; } } public Widget(int argx, int argy) { x = argx; y = argy; } public int CompareTo(object obj) { int result = 1; if (obj != null && obj is Widget) { Widget w = obj as Widget; result = this.X.CompareTo(w.X); } return result; } static public int Compare(Widget x, Widget y) { int result = 1; if (x != null && y != null) { result = x.CompareTo(y); } return result; } }
I implemented IComparable, so it can be unstably sorted by List.Sort().
However, I also implemented the static method Compare, which can be passed as a delegate to a search method.
I borrowed this insertion sort method from C# 411:
public static void InsertionSort<T>(IList<T> list, Comparison<T> comparison) { int count = list.Count; for (int j = 1; j < count; j++) { T key = list[j]; int i = j - 1; for (; i >= 0 && comparison(list[i], key) > 0; i--) { list[i + 1] = list[i]; } list[i + 1] = key; } }
You would put this in the sort helpers class that you mentioned in your question.
Now, to use it:
static void Main(string[] args) { List<Widget> widgets = new List<Widget>(); widgets.Add(new Widget(0, 1)); widgets.Add(new Widget(1, 1)); widgets.Add(new Widget(0, 2)); widgets.Add(new Widget(1, 2)); InsertionSort<Widget>(widgets, Widget.Compare); foreach (Widget w in widgets) { Console.WriteLine(w.X + ":" + w.Y); } }
And it outputs:
0:1 0:2 1:1 1:2 Press any key to continue . . .
This could probably be cleaned up with some anonymous delegates, but I'll leave that up to you.
EDIT: And NoBugz demonstrates the power of anonymous methods...so, consider mine more oldschool :P