Інтерфейс IComparable визначений в просторі імен System. Він містить всього один метод CompareTo, що повертає результат порівняння двох об'єктів, - поточного і переданого йому як параметр:
interface IComparable
{
int CompareTo( object obj )
}
Метод повинен повертати:
· 0, якщо поточний об'єкт і параметр рівні;
· від’ємне число, якщо поточний об'єкт менше параметра;
· додатне число, якщо поточний об'єкт більше параметра.
Реалізуємо інтерфейс IComparable в знайомому нам класі Monster. Як критерій порівняння об'єктів виберемо поле health. У лістингу 9.2 приведена програма, що сортує масив монстрів за збільшенням величини, що характеризує їх здоров'я (елементи класу, що не використовуються в даній програмі, не приводяться).
Лістинг 9.2. Приклад реалізації інтерфейсу IComparable
using System;
// Стандартні інтерфейси .NET
namespace examp55
{
class Monster : IComparable
{
public Monster(int health, int ammo, string name)
{
this.health = health ;
this.ammo = ammo;
this.name = name;
}
virtual public void Passport()
{
Console.WriteLine("Monster {0} \t healt h = {1} ammo = {2}",
name, health, ammo);
}
public int CompareTo(object obj) // реализація інтерфейсу
{
Monster temp = (Monster)obj;
if (this.health > temp.health) return 1;
if (this.health < temp.health) return -1;
return 0;
}
string name;
int health, ammo;
}
class Class1
{
static void Main()
{
const int n = 3;
Monster[] stado = new Monster[n];
stado[0] = new Monster(50, 50, "V");
stado[1] = new Monster(80, 80, "P");
stado[2] = new Monster(40, 10, "M");
Array.Sort(stado); // сортування стало можливим
foreach (Monster elem in stado) elem.Passport();
}
}
}
Результат роботи програми:
Monster Маша health = 40 ammo = 10
Monster Вася health = 50 ammo = 50
Monster Петя health = 80 ammo = 80
Якщо декілька об'єктів мають однакове значення критерію сортування, їх відносний порядок проходження після сортування не зміниться.
У багатьох алгоритмах потрібно виконувати сортування об'єктів по різних критеріях. У С# для цього використовується інтерфейс IComparer.
9.5.2 Сортування по різних критеріях (інтерфейс IComparer)
Інтерфейс IComparer визначений в просторі імен System.Collections. Він містить один метод CompareTo, що повертає результат порівняння двох об'єктів, переданих йому як параметри:
interface IComparer
{
int Compare ( object ob1, object ob2 )
}
Принцип застосування цього інтерфейсу полягає в тому, що для кожного критерію сортування об'єктів описується невеликий допоміжний клас, що реалізовує цей інтерфейс. Об'єкт цього класу передається в стандартний метод сортування масиву як другий аргумент (існує декілька перевантажених версій цього методу).
Приклад сортування масиву об'єктів з попереднього лістингу по іменах (властивість Name, клас Sortbyname) і кількості озброєнь (властивість Ammo, клас Sortbyammo) приведений в лістингу 9.3. Класи параметрів сортування оголошені вкладеними, оскільки вони потрібні тільки об'єктам класу Monster.
Лістинг 9.3. Сортування по двом критеріям
using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace examp56
{
class Monster
{
string name;
int health;
int ammo;
public Monster(int health, int ammo, string name)
{
this.health = health;
this.ammo = ammo;
this.name = name;
}
public int Ammo
{
get { return ammo; }
set
{
if (value > 0) ammo = value; else ammo = 0;
}
}
public string Name
{
get { return name; }
}
virtual public void Passport()
{
Console.WriteLine("Monster {0} \t health - {1} ammo - {2}",
name, health, ammo);
}
public class SortByName : IComparer
{
int IComparer.Compare(object ob1, object ob2)
{
Monster m1 = (Monster)ob1;
Monster m2 = (Monster)ob2;
return String.Compare(m1.Name, m2.Name);
}
}
public class SortByAmmo : IComparer
{
int IComparer.Compare(object ob1, object ob2)
{
Monster m1 = (Monster)ob1;
Monster m2 = (Monster)ob2;
if (m1.Ammo > m2.Ammo) return 1;
if (m1.Ammo < m2.Ammo) return -1;
return 0;
}
}
}
class Program
{
static void Main(string[] args)
{
const int n = 3;
Monster[] stado = new Monster[n];
stado[0] = new Monster(50, 50, "Вася");
stado[1] = new Monster(80, 80, "Петя");
stado[2] = new Monster(40, 10, "Маша");
Console.WriteLine("Сортировка по имени:");
Array.Sort(stado, new Monster.SortByName());
foreach (Monster elem in stado) elem.Passport();
Console.WriteLine("Сортировка по вооружению:");
Array.Sort(stado, new Monster.SortByAmmo());
foreach (Monster elem in stado) elem.Passport();
}
}
}
Результат роботи програми:
Сортування по імені:
Monster Вася health = 50 ammo 50
Monster Маша health = 40 ammo 10
Monster Петя health = 80 ammo 30
Сортування по озброєнню:
Monster Маша health = 40 ammo 10
Monster Вася health = 50 ammo 50
Monster Петя health = 80 ammo 80