Реализация интерфейса IComparer
56C# --- Руководство по C# --- Реализация интерфейса IComparer
Для сортировки объектов определяемых пользователем классов зачастую проще всего реализовать в этих классах интерфейс IComparable. Тем не менее данную задачу можно решить и с помощью интерфейса IComparer. Для этой цели необходимо сначала создать класс, реализующий интерфейс IComparer, а затем указать объект этого класса, когда потребуется сравнение.
Интерфейс IComparer существует в двух формах: обобщенной и необобщенной. Несмотря на сходство применения обеих форм данного интерфейса, между ними имеются некоторые, хотя и небольшие, отличия.
В необобщенном интерфейсе IComparer определяется только один метод Compare():
int Compare(object x, object у)
В методе Compare() сравниваются объекты х и у. Для сортировки объектов по нарастающей конкретная реализация данного метода должна возвращать нулевое значение, если значения сравниваемых объектов равны; положительное — если значение объекта х больше, чем у объекта у; и отрицательное — если значение объекта х меньше, чем у объекта у. А для сортировки по убывающей можно обратить результат сравнения объектов. Если же тип объекта x не подходит для сравнения с объектом y, то в методе Compare() может быть сгенерировано исключение ArgumentException.
Объект типа IComparer может быть указан при конструировании объекта класса SortedList, при вызове метода ArrayList.Sort(IComparer), а также в ряде других мест в классах коллекций. Главное преимущество применения интерфейса IComparer заключается в том, что сортировке подлежат объекты тех классов, в которых интерфейс IComparable не реализуется.
Интерфейс IComparer<T> является обобщенным вариантом интерфейса IComparer. В нем определяется приведенный ниже обобщенный вариант метода Compare():
int Compare(Т х, T у)
В этом методе сравниваются объекты х и у и возвращается нулевое значение, если значения сравниваемых объектов равны; положительное — если значение объекта х больше, чем у объекта у; и отрицательное — если значение объекта х меньше, чем у объекта у.
Давайте рассмотрим пример:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class AutoShop
{
public string CarName { set; get; }
public int MaxSpeed { get; set; }
public double Cost { get; set; }
public byte Discount { get; set; }
public int ID { get; set; }
public AutoShop() { }
public AutoShop(string CarName, int MaxSpeed, double Cost, byte Discount, int ID)
{
this.CarName = CarName;
this.MaxSpeed = MaxSpeed;
this.Cost = Cost;
this.Discount = Discount;
this.ID = ID;
}
public override string ToString()
{
return String.Format("{4}\tМарка: {0}\tМакс. скорость: {1}\tЦена: {2:C}\tСкидка: {3}%",
this.CarName,this.MaxSpeed,this.Cost,this.Discount,this.ID);
}
}
class CompInv<T> : IComparer<T>
where T : AutoShop
{
// Реализуем интерфейс IComparer<T>
public int Compare(T x, T y)
{
if (x.Cost < y.Cost)
return 1;
if (x.Cost > y.Cost)
return -1;
else return 0;
}
}
class Program
{
static void Main()
{
CompInv<AutoShop> cp = new CompInv<AutoShop>();
List<AutoShop> dic = new List<AutoShop>();
// Создадим множество автомобилей
dic.Add(new AutoShop("Toyota Corolla", 180, 300000, 5, 1));
dic.Add(new AutoShop("VAZ 2114i", 160, 220000, 0, 2));
dic.Add(new AutoShop("Daewoo Nexia", 140, 260000, 5, 3));
dic.Add(new AutoShop("Honda Torneo", 220, 400000, 7, 4));
dic.Add(new AutoShop("Audi R8 Best", 360, 4200000, 3, 5));
Console.WriteLine("Исходный каталог автомобилей: \n");
Console.WindowWidth = 100;
foreach (AutoShop a in dic)
Console.WriteLine(a);
Console.WriteLine("\nТеперь автомобили отсортированны по стоимости: \n");
dic.Sort(cp);
foreach (AutoShop a in dic)
Console.WriteLine(a);
Console.ReadLine();
}
}
}