Книга: C# 4.0: полное руководство
Реализация интерфейса IComparable
Разделы на этой странице:
Реализация интерфейса IComparable
Если требуется отсортировать коллекцию, состоящую из объектов определяемого пользователем класса, при условии, что они не сохраняются в коллекции класса SortedList
, где элементы располагаются в отсортированном порядке, то в такой коллекции должен быть известен способ сортировки содержащихся в ней объектов. С этой целью можно, в частности, реализовать интерфейс IComparable для объектов сохраняемого типа. Интерфейс IComparable
доступен в двух формах: обобщенной и необобщенной. Несмотря на сходство применения обеих форм данного интерфейса, между ними имеются некоторые, хотя и небольшие, отличия, рассматриваемые ниже.
Реализация интерфейса IComparable для необобщенных коллекций
Если требуется отсортировать объекты, хранящиеся в необобщенной коллекции, то для этой цели придется реализовать необобщенный вариант интерфейса IComparable
. В этом варианте данного интерфейса определяется только один метод, CompareTo()
, который определяет порядок выполнения самого сравнения. Ниже приведена общая форма объявления метода CompareTo()
.
int CompareTo(object obj)
В методе CompareTo()
вызывающий объект сравнивается с объектом obj. Для сортировки объектов по нарастающей конкретная реализация данного метода должна возвращать нулевое значение, если значения сравниваемых объектов равны; положительное — если значение вызывающего объекта больше, чем у объекта obj; и отрицательное — если значение вызывающего объекта меньше, чем у объекта obj. А для сортировки по убывающей можно обратить результат сравнения объектов. Если же тип объекта obj не подходит для сравнения с вызывающим объектом, то в методе CompareTo()
может быть сгенерировано исключение ArgumentException
.
В приведенном ниже примере программы демонстрируется конкретная реализация интерфейса IComparable
. В этой программе интерфейс IComparable
вводится в класс Inventory
, разработанный в двух последних примерах из предыдущего раздела. В классе Inventory
реализуется метод CompareTo()
для сравнения полей name объектов данного класса, что дает возможность отсортировать товарные запасы по наименованию. Как показано в данном примере программы, коллекция объектов класса Inventory подлежит сортировке благодаря реализации интерфейса IComparable
в этом классе.
// Реализовать интерфейс IComparable.
using System;
using System.Collections;
// Реализовать необобщенный вариант интерфейса IComparable.
class Inventory : IComparable {
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:C} Наличие: {2}", name, cost, onhand);
}
// Реализовать интерфейс IComparable.
public int CompareTo(object obj) {
Inventory b;
b = (Inventory)obj;
return name.CompareTo(b.name);
}
}
class IComparableDemo {
static void Main() {
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();
// Отсортировать список,
inv.Sort();
Console.WriteLine("Перечень товарных запасов после сортировки:");
foreach (Inventory i in inv) {
Console.WriteLine(" " + i);
}
}
}
Ниже приведен результат выполнения данной программы. Обратите внимание на то, что после вызова метода Sort() товарные запасы оказываются отсортированными по наименованию.
Перечень товарных запасов до сортировки:
Кусачки Стоимость: $5,95 Наличие: 3
Отвертки Стоимость: $8,29 Наличие: 2
Молотки Стоимость: $3,50 Наличие: 4
Дрели Стоимость: $19,88 Наличие: 8
Перечень товарных запасов после сортировки:
Дрели Стоимость: $19,88 Наличие: 8
Кусачки Стоимость: $5,95 Наличие: 3
Молотки Стоимость: $3,50 Наличие: 4
Отвертки Стоимость: $8,29 Наличие: 2
Реализация интерфейса IComparable для обобщенных коллекций
Если требуется отсортировать объекты, хранящиеся в обобщенной коллекции, то для этой цели придется реализовать обобщенный вариант интерфейса IComparable<T>
. В этом варианте интерфейса IComparable
определяется приведенная ниже обобщенная форма метода CompareTo()
.
int CompareTo(Т other)
В методе CompareTo()
вызывающий объект сравнивается с другим объектом other. Для сортировки объектов по нарастающей конкретная реализация данного метода должна возвращать нулевое значение, если значения сравниваемых объектов равны; положительное — если значение вызывающего объекта больше, чем у объекта другого other; и отрицательное — если значение вызывающего объекта меньше, чем у другого объекта other. А для сортировки по убывающей можно обратить результат сравнения объектов. При реализации обобщенного интерфейса IComparable<T>
имя типа реализующего класса обычно передается в качестве аргумента типа.
Приведенный ниже пример программы является вариантом предыдущего примера, измененным с целью реализовать и использовать обобщенный интерфейс IComparable<T>
. Обратите внимание на применение класса обобщенной коллекции List<T>
вместо класса необобщенной коллекции ArrayList
.
// Реализовать интерфейс IComparable<T>.
using System;
using System.Collections.Generic;
// Реализовать обобщенный вариант интерфейса IComparable<T>.
class Inventory : IComparable<Inventory> {
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:C} Наличие: {2}", name, cost, onhand);
}
// Реализовать интерфейс IComparable<T>.
public int CompareTo(Inventory obj) {
return name.CompareTo(obj.name);
}
}
class GenericIComparableDemo {
static void Main() {
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();
// Отсортировать список,
inv.Sort();
Console.WriteLine("Перечень товарных запасов после сортировки:");
foreach (Inventory i in inv) {
Console.WriteLine(" " + i);
}
}
}
Эта версия программы дает такой же результат, как и предыдущая, необобщенная версия.
- Краткий обзор коллекций
- Необобщенные коллекции
- Хранение отдельных битов в классе коллекции BitArray
- Специальные коллекции
- Обобщенные коллекции
- Параллельные коллекции
- Сохранение объектов, определяемых пользователем классов, в коллекции
- Реализация интерфейса IComparable
- Применение интерфейса IComparer
- Применение класса StringComparer
- Доступ к коллекции с помощью перечислителя
- Реализация интерфейсов IEnumerable и IEnumerator
- Применение итераторов
- Инициализаторы коллекций
- Реализация нескольких интерфейсов
- 9.4.1. Реализация графа в виде матрицы смежности
- Реализация языка SQL
- 9.2.1. Более строгая реализация стека
- 9.2 Реализация массива ftAID на платформе Windows NT
- Не допускайте того, чтобы поток пользовательского интерфейса блокировался на длительное время
- Реализация семафоров в Linux
- Основы интерфейса Access 2007
- Урок 2.3. Настройка интерфейса Windows Vista
- Настройка интерфейса Word
- 16.8. Реализация отношений в Core Data
- 10.16. Реализация с использованием семафоров System V