Книга: C# 4.0: полное руководство

Применение интерфейса IComparer

Применение интерфейса IComparer

Для сортировки объектов определяемых пользователем классов зачастую проще всего реализовать в этих классах интерфейс IComparable. Тем не менее данную задачу можно решить и с помощью интерфейса IComparer. Для этой цели необходимо сначала создать класс, реализующий интерфейс IComparer, а затем указать объект этого класса, когда потребуется сравнение.

Интерфейс IComparer существует в двух формах: обобщенной и необобщенной. Несмотря на сходство применения обеих форм данного интерфейса, между ними имеются некоторые, хотя и небольшие, отличия, рассматриваемые ниже.

Применение необобщенного интерфейса icomparer

В необобщенном интерфейсе IComparer определяется только один метод, Compare().

int Compare(object x, object y)

В методе Compare() сравниваются объекты x и у. Для сортировки объектов по нарастающей конкретная реализация данного метода должна возвращать нулевое значение, если значения сравниваемых объектов равны; положительное — если значение объекта х больше, чем у объекта у; и отрицательное — если значение объекта х меньше, чем у объекта у. А для сортировки по убывающей можно обратить результат сравнения объектов. Если же тип объекта х не подходит для сравнения с объектом у, то в методе CompareTo() может быть сгенерировано исключение ArgumentException.

Объект типа IComparer может быть указан при конструировании объекта класса SortedList, при вызове метода ArrayList.Sort(IComparer), а также в ряде других мест в классах коллекций. Главное преимущество применения интерфейса IComparer заключается в том, что сортировке подлежат объекты тех классов, в которых интерфейс IComparable не реализуется.

Приведенный ниже пример программы является вариантом рассматривавшегося ранее необобщенного примера программы учета товарных запасов, переделанного с целью воспользоваться интерфейсом IComparer для сортировки перечня товарных запасов. В этом варианте программы сначала создается класс CompInv, в котором реализуется интерфейс IComparer и сравниваются два объекта класса Inventory. А затем объект класса Complnv указывается в вызове метода Sort() для сортировки перечня товарных запасов.

// Применение необобщеннкого варианта интерфейса  IComparer
using System;
using System.Collections;
// Создать объект типа IComparer для объектов класса Inventory,
class CompInv : IComparer {
  // Реализовать интерфейс IComparer.
  public int Compare(object x, object y) {
    Inventory a, b;
    a = (Inventory)x;
    b = (Inventory)y;
    return string.Compare(a.name, b.name, StringComparison.Ordinal);
  }
}
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} Цена: {1,6:С} В наличии: {2}",
name, cost, onhand);
  }
}
class IComparerDemo {
  static void Main() {
    CompInv comp = new CompInv();
    ArrayList inv = new ArrayList();
    // Добавить элементы в список.
    inv.Add(new Inventory("Кусачки", 5.95, 3));
    inv.Add(new Inventory("Отвертки", 8.29, 2));
    inv.Add(new Inventory("Молотки", 3.50, 4));
    inv.Add(new Inventory("Дрели", 19.88, 8));
    Console.WriteLine("Перечень товарных запасов до сортировки:");
    foreach (Inventory i in inv) {
      Console.WriteLine("    " + i);
    }
    Console.WriteLine();
    // Отсортировать список, используя интерфейс IComparer.
    inv.Sort(comp);
    Console.WriteLine("Перечень товарных запасов после сортировки:");
    foreach (Inventory i in inv) {
      Console.WriteLine("    " + i);
    }
  }
}

Эта версия программы дает такой же результат, как и предыдущая.

Применение обобщенного интерфейса IСоmрагег<T>

Интерфейс IComparer<T> является обобщенным вариантом интерфейса IComparer. В нем определяется приведенный ниже обобщенный вариант метода Compare().

int Compare(Т х, Т у)

В этом методе сравниваются объекты х и у и возвращается нулевое значение, если значения сравниваемых объектов равны; положительное — если значение объекта х больше, чем у объекта у; и отрицательное — если значение объекта х меньше, чем у объекта у.

Ниже приведена обобщенная версия предыдущей программы учета товарных запасов, в которой теперь используется интерфейс IComparer<Т>. Она дает такой же результат, как и необобщенная версия этой же программы.

// Использовать обобщенный вариант интерфейса IComparer<T>.
using System;
using System.Collections.Generic;
// Создать объект типа IComparer<T> для объектов класса Inventory,
class CompInv<T> : IComparer<T> where T : Inventory {
  // Реализовать интерфейс IComparer<T>.
  public int Compare(T x, T y) {
    return string.Compare(x.name, y.name, StringComparison.Ordinal);
  }
}
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} Цена: {1,6:С} В наличии: {2}",
                    name, cost, onhand);
  }
}
class GenericIComparerDemo {
  static void Main() {
    CompInv<Inventory> comp = new CompInv<Inventory>();
    List<Inventory> inv = new List<Inventory>();
   // Добавить элементы в список.
    inv.Add(new Inventory("Кусачки", 5.95, 3));
    inv.Add(new Inventory("Отвертки", 8.29, 2));
    inv.Add(new Inventory("Молотки", 3.50, 4));
    inv.Add(new Inventory("Дрели", 19.88, 8));
    Console.WriteLine("Перечень товарных запасов до сортировки:");
    foreach (Inventory i in inv) {
      Console.WriteLine("    " + i);
    }
    Console.WriteLine();
    // Отсортировать список, используя интерфейс IComparer.
    inv.Sort(comp);
    Console.WriteLine("Перечень товарных запасов после сортировки:");
    foreach (Inventory i in inv) {
      Console.WriteLine("    " + i);
    }
  }
}

Оглавление книги


Генерация: 1.984. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз