Subscribe

RSS Feed (xml)

Using an IComparer

Although implementing IComparable for classes that you create is often the easiest way to allow objects of those classes to be sorted, you can approach the problem a different way by using IComparer. To use IComparer, first create a class that implements IComparer, and then specify an object of that class when comparisons are required.
There are two versions of IComparer: generic and non-generic. Each approach is examined here.

Using a Non-Generic IComparer

The non-generic IComparer defines only one method, Compare( ), which is shown here:
int Compare(object obj1, object obj2)
Compare( ) compares obj1 to obj2. To sort in ascending order, your implementation must return zero if the objects are equal, a positive value if obj1 is greater than obj2, and a negative value if obj1 is less than obj2. You can sort in descending order by reversing the outcome of the comparison. The method can throw an ArgumentException if the type of obj is not compatible for comparison with the invoking object.
An IComparer can be specified when constructing a SortedList, when calling ArrayList.Sort(IComparer), and at various other places throughout the collection classes. The main advantage of using IComparer is that you can sort objects of classes that do not implement IComparable.
The following program reworks the inventory program so that it uses an IComparer to sort the inventory list. It first creates a class called CompInv that implements IComparer and compares two Inventory objects. An object of this class is then used in a call to Sort( ) to sort the inventory list.
// Use IComparer.

using System;
using System.Collections;

// Create an IComparer for Inventory objects.
class CompInv : IComparer {
  // Implement the IComparer interface.
  public int Compare(object obj1, object obj2) {
    Inventory a, b;
    a = (Inventory) obj1;
    b = (Inventory) obj2;
    return a.name.CompareTo(b.name);
  }
}

class Inventory {
  public string name;
  double cost;
  int onhand;

  public Inventory(string n, double c, int h) {
    name = n;
    cost = c;
    onhand = h;
  }

  public override string ToString() {
    return
      String.Format("{0,-10}Cost: {1,6:C}  On hand: {2}",
                    name, cost, onhand);
  }
}

class IComparerDemo {
  public static void Main() {
    CompInv comp = new CompInv();
    ArrayList inv = new ArrayList();

    // Add elements to the list
    inv.Add(new Inventory("Pliers", 5.95, 3));
    inv.Add(new Inventory("Wrenches", 8.29, 2));
    inv.Add(new Inventory("Hammers", 3.50, 4));
    inv.Add(new Inventory("Drills", 19.88, 8));

    Console.WriteLine("Inventory list before sorting:");
    foreach(Inventory i in inv) {
      Console.WriteLine("   " + i);
    }
    Console.WriteLine();
    // Sort the list using an IComparer.
    inv.Sort(comp);

    Console.WriteLine("Inventory list after sorting:");
    foreach(Inventory i in inv) {
      Console.WriteLine("   " + i);
    }
  }
}
The output is the same as for the previous version of the program.

Using a Generic IComparer

The IComparer interface is the generic version of IComparer. It defines the generic version of Compare( ) shown here:
int Compare(T obj1, T obj2)
This method compares obj1 with obj2 and returns greater than zero if obj1 is greater than obj2, zero if the two objects are the same, and less than zero if obj1 is less than obj2.
Here is a generic version of the preceding program that uses IComparer. It produces the same output as the previous versions of the program.
// Use IComparer.

using System;
using System.Collections.Generic;

// Create an IComparer for Inventory objects.
class CompInv : IComparer where T : Inventory {

  // Implement the IComparer interface.
  public int Compare(T obj1, T obj2) {
    return obj1.name.CompareTo(obj2.name);
  }

}

class Inventory {
  public string name;
  double cost;
  int onhand;

  public Inventory(string n, double c, int h) {
    name = n;
    cost = c;
    onhand = h;
  }

  public override string ToString() {
    return
      String.Format("{0,-10}Cost: {1,6:C}  On hand: {2}",
                    name, cost, onhand);
  }
}
class GenericIComparerDemo {
  public static void Main() {
    CompInv comp = new CompInv();
    List inv = new List();

    // Add elements to the list
    inv.Add(new Inventory("Pliers", 5.95, 3));
    inv.Add(new Inventory("Wrenches", 8.29, 2));
    inv.Add(new Inventory("Hammers", 3.50, 4));
    inv.Add(new Inventory("Drills", 19.88, 8));

    Console.WriteLine("Inventory list before sorting:");
    foreach(Inventory i in inv) {
      Console.WriteLine("   " + i);
    }
    Console.WriteLine();

    // Sort the list using an IComparer.
    inv.Sort(comp);

    Console.WriteLine("Inventory list after sorting:");
    foreach(Inventory i in inv) {
      Console.WriteLine("   " + i);
    }
  }
}

No comments:

Post a Comment

Archives

LocalsAdda.com-Variety In Web World

Fun Mail - Fun in the Mail