Sort and provide custom sorts for standard data types and objects in C#
Sorting algorithms are absolutely fascinating and I recommend that everyone study them at some point. Different algorithms demonstrate interesting and useful techniques such as recursion, divide-and-conquer, linked data structures, heaps, balanced trees, and randomization to prevent worst-case performance.
However, the .NET Framework provides some very good sorting tools so, unless the data has a special structure that you can use to your advantage, you will probably not beat the built-in routines by much. So follow one of my standard pieces of advice:
First make it work. Then make it work faster if necessary.To sort an array of a simple data structure, use the Array.Sort method. This example builds an array of random numbers named numbers. It displays the list, sorts it using the following code, and displays the sorted version.
Array.Sort(numbers);It's hard to imagine anything simpler! Unfortunately this method doesn't work with an array of objects. For example, suppose you build a Person class with the usual fields: FirstName, LastName, Street, City, State, Zip, Phone, and so forth. There's no way the Array.Sort method can know how you would want a list of these objects sorted. Should it sort by name? Last-name-first or last? By ZIP code, perhaps for a mailing list? One way to give Array.Sort the ability to sort these objects is to make the class implement the IComparable interface. An interface defines properties, methods, and events that the class must provide but it doesn't say how they must be provided. The IComparable interface says the class must provide a CompareTo method that takes an object as a parameter and returns a value less than, equal to, or greater than 0 to indicate whether this object (a Person) should be considered less than, equal to, or greater than another object (another Person). Now Array.Sort can use that method to compare two Person objects so it can sort an array of Persons. To implement an interface, make the class "inherit" from the interface. This program's Person class is declared with this code:
class Person : IComparableThe class uses the following code to provide the CompareTo method.
// Compare two Person's names.Having make the CompareTo class implement IComparable, the program creates an array of Person objects and then sorts them using this code:
public int CompareTo(object obj)
{
if (!(obj is Person))
throw new ArgumentException("Object is not a Person");
Person person = obj as Person;
return ToString().CompareTo(person.ToString());
}
Array.Sort(people);Easy, peasy. But suppose you sometimes want to sort Person objects in some other way. For example, suppose you sometimes want to sort them last-name-first. The Person class's CompareTo method sorts first name first so it won't do it. To handle this problem, the Array.Sort method can take a second parameter that gives an object that implements the IComparer interface. Array.Sort uses that object to compare two Person objects while it sorts. The IComparer interface requires that a class provide a Compare method that compares two objects. The following code shows the IComparer class used by this example. Notice that it implements the generic IComparer interface so the Compare method is strongly typed to use Person objects.
class PersonComparer : IComparerThe example program uses the following code to sort a list of Person objects in last-name-first order.{
// Compare two Persons.
public int Compare(Person person1, Person person2)
{
string name1 = person1.LastName + "," + person1.FirstName;
string name2 = person2.LastName + "," + person2.FirstName;
return name1.CompareTo(name2);
}
}
PersonComparer comparer = new PersonComparer();Note that the program overrides the Person class's ToString method to allow its ListBoxes to display Person objects nicely. For more information, see Override a class's ToString method to allow controls such as ListBox to display objects in C#.
Array.Sort(people, comparer);



Comments