You have
a data type that will be stored as elements in an array or an
ArrayList
. You would like to use the
Array.Sort
and ArrayList.Sort
methods to allow for a custom sorting of your data types in the
array. In addition, you may need to use this structure in a
SortedList
collection.
Implement the
IComparable
interface. The following class,
Square
, implements this interface in a way so that
the Array
, ArrayList
, and
SortedList
objects can sort and search an array or
collection of these Square
objects:
public class Square : IComparable { public Square( ){} public Square(int height, int width) { this.height = height; this.width = width; } private int height; private int width; public int Height { get{ return (height); } set{ height = value; } } public int Width { get{ return (width); } set{ width = value; } } public int CompareTo(object obj) { if (this.GetType( ) != obj.GetType( )) { throw (new ArgumentException( "Both objects being compared must be of type Square.")); } else { Square square2 = (Square)obj; long area1 = this.Height * this.Width; long area2 = square2.Height * square2.Width; if (area1 == area2) { return (0); } else if (area1 > area2) { return (1); } else if (area1 < area2) { return (-1); } else { return (-1); } } } public override string ToString( ) { return ("Height:" + height + " Width:" + width); } }
By implementing the IComparable
interface on your
class (or structure), you can take advantage of the sorting routines
of the Array
, ArrayList
, and
SortedList
classes. The algorithms for sorting are
built into these classes; all you have to do is tell them how to sort
through your classes via the code you implement in the
IComparable.CompareTo
method.
When an array of Square
objects is passed to the
Array.Sort
static method, the array is sorted
using the IComparable
interface of the
Square
objects. The same goes for the
ArrayList.Sort
method. The
Add
method of the
SortedList
class uses this interface to sort the
objects as they are being added to the SortedList
.
The algorithm that the Array.Sort
and
ArrayList.Sort
methods use to sort an
array’s elements is the QuickSort
algorithm.
IComparer
is designed to solve the problem of
allowing objects to be sorted based on different criteria in
different contexts. This interface also allows us to sort types that
we did not write. If we wanted to also be able to sort the
Square
objects by height, we could create a new
class called CompareHeight
, which would also
implement the IComparer
interface:
public class CompareHeight : IComparer { public int Compare(object obj1, object obj2) { if (!(obj1 is Square) || !(obj2 is Square)) { throw (new ArgumentException("Both parameters must be of type Square.")); } else { Square square1 = (Square)obj1; Square square2 = (Square)obj2; if (square1.Height == square2.Height) { return (0); } else if (square1.Height > square2.Height) { return (1); } else if (square1.Height < square2.Height) { return (-1); } else { return (-1); } } } }
This class is then passed in to the IComparer
parameter of the Sort
routine. Now we can specify
different ways to sort our Square
objects.
For best performance, keep the CompareTo
method
short and efficient, since it will be called multiple times by the
Sort
methods. For example, in sorting an array
with 4 items, the Compare
method was called 10
times.
The following method shows how to use the Square
and CompareHeight
structures with the
Array
, ArrayList
, and
SortedList
classes:
public static void TestSort( ) { Square[] arrayOfSquares = new Square[4] {new Square(1,3), new Square(4,3), new Square(2,1), new Square(6,1)}; ArrayList arrayListOfSquares = new ArrayList( ); arrayListOfSquares.Add(new Square(1,3)); arrayListOfSquares.Add(new Square(4,3)); arrayListOfSquares.Add(new Square(2,1)); arrayListOfSquares.Add(new Square(6,1)); IComparer HeightCompare = new CompareHeight( ); // Test an ARRAY Console.WriteLine("ARRAY"); Console.WriteLine("Original array"); foreach (Square s in arrayOfSquares) { Console.WriteLine(s.ToString( )); } Console.WriteLine( ); Console.WriteLine("Sorted array using IComparer=HeightCompare"); Array.Sort(arrayOfSquares, HeightCompare); foreach (Square s in arrayOfSquares) { Console.WriteLine(s.ToString( )); } Console.WriteLine( ); Console.WriteLine("Sorted array using IComparable"); Array.Sort(arrayOfSquares); foreach (Square s in arrayOfSquares) { Console.WriteLine(s.ToString( )); } // Test an ARRAYLIST Console.WriteLine( ); Console.WriteLine( ); Console.WriteLine("ARRAYLIST"); foreach (Square s in arrayListOfSquares) { Console.WriteLine(s.ToString( )); } Console.WriteLine( ); Console.WriteLine("Sorted ArrayList using IComparer=HeightCompare"); arrayListOfSquares.Sort(HeightCompare); foreach (Square s in arrayListOfSquares) { Console.WriteLine(s.ToString( )); } Console.WriteLine( ); Console.WriteLine("Sorted ArrayList using IComparable"); arrayListOfSquares.Sort( ); foreach (Square s in arrayListOfSquares) { Console.WriteLine(s.ToString( )); } // Test a SORTEDLIST SortedList SortedListOfSquares = new SortedList( ); SortedListOfSquares.Add(0, new Square(1,3)); SortedListOfSquares.Add(2, new Square(4,3)); SortedListOfSquares.Add(1, new Square(2,1)); SortedListOfSquares.Add(3, new Square(6,1)); Console.WriteLine( ); Console.WriteLine( ); Console.WriteLine("SORTEDLIST"); foreach (DictionaryEntry s in SortedListOfSquares) { Console.WriteLine(s.Key + " : " + ((Square)s.Value).ToString( )); } }
This code displays the following output:
ARRAY Original array Height:1 Width:3 Height:4 Width:3 Height:2 Width:1 Height:6 Width:1 Sorted array using IComparer=HeightCompare Height:1 Width:3 Height:2 Width:1 Height:4 Width:3 Height:6 Width:1 Sorted array using IComparable Height:2 Width:1 Height:1 Width:3 Height:6 Width:1 Height:4 Width:3 ARRAYLIST Height:1 Width:3 Height:4 Width:3 Height:2 Width:1 Height:6 Width:1 Sorted ArrayList using IComparer=HeightCompare Height:1 Width:3 Height:2 Width:1 Height:4 Width:3 Height:6 Width:1 Sorted ArrayList using IComparable Height:2 Width:1 Height:1 Width:3 Height:6 Width:1 Height:4 Width:3 SORTEDLIST 0 : Height:1 Width:3 1 : Height:2 Width:1 2 : Height:4 Width:3 3 : Height:6 Width:1
See Recipe 3.6; see the “IComparable Interface” topic in the MSDN documentation.