...
// Реализация интерфейса IComparable.
int IComparable.CompareTo(object obj)
{
if (obj is Car temp)
{
if (this.CarID > temp.CarID)
{
return 1;
}
if (this.CarID < temp.CarID)
{
return -1;
}
return 0;
}
throw new ArgumentException("Parameter is not a Car!");
// Параметр не является объектом типа Car!
}
}
Как видите, логика метода CompareTo() заключается в сравнении входного объекта с текущим экземпляром на основе специфичного элемента данных. Возвращаемое значение метода CompareTo() применяется для выяснения того, является текущий объект меньше, больше или равным объекту, с которым он сравнивается (табл. 8.1).
Предыдущую реализацию метода CompareTo() можно усовершенствовать с учетом того факта, что тип данных int в C# (который представляет собой просто сокращенное обозначение для типа System.Int32) реализует интерфейс IComparable. Реализовать CompareTo() в Car можно было бы так:
int IComparable.CompareTo(object obj)
{
if (obj is Car temp)
{
return this.CarID.CompareTo(temp.CarID);
}
throw new ArgumentException("Parameter is not a Car!");
// Параметр не является объектом типа Car!
}
В любом случае, поскольку тип Car понимает, как сравнивать себя с подобными объектами, вы можете написать следующий тестовый код:
// Использование интерфейса IComparable.
// Создать массив объектов Car.
...
// Отобразить текущее содержимое массива.
Console.WriteLine("Here is the unordered set of cars:");
foreach(Car c in myAutos)
{
Console.WriteLine("{0} {1}", c.CarID, c.PetName);
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
}
// Теперь отсортировать массив с применением IComparable!
Array.Sort(myAutos);
Console.WriteLine();
// Отобразить отсортированное содержимое массива.
Console.WriteLine("Here is the ordered set of cars:");
foreach(Car c in myAutos)
{
Console.WriteLine("{0} {1}", c.CarID, c.PetName);
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
}
Console.ReadLine();
Ниже показан вывод, полученный в результате выполнения приведенного выше кода:
***** Fun with Object Sorting *****
Here is the unordered set of cars:
1 Rusty
234 Mary
34 Viper
4 Mel
5 Chucky
Here is the ordered set of cars:
1 Rusty
4 Mel
5 Chucky
34 Viper
234 Mary
Указание множества порядков сортировки с помощью IComparer
В текущей версии класса Car в качестве основы для порядка сортировки используется идентификатор автомобиля (CarID). В другом проектном решении основой сортировки могло быть дружественное имя автомобиля (для вывода списка автомобилей в алфавитном порядке). А что если вы хотите построить класс Car, который можно было бы подвергать сортировке по идентификатору и также по дружественному имени? В таком случае вы должны ознакомиться с еще одним стандартным интерфейсом по имени IComparer, который определен в пространстве имен System.Collections следующим образом:
// Общий способ сравнения двух объектов.
interface IComparer
{
int Compare(object o1, object o2);
}
На заметку! Обобщенная версия этого интерфейса (IСоmраrаble<Т>) обеспечивает более безопасный в отношении типов способ обработки операций сравнения объектов. Обобщения подробно рассматриваются в главе 10.
В отличие от IСоmраrаble интерфейс IComparer обычно не реализуется в типе, который вы пытаетесь сортировать (т.е. Car). Взамен данный интерфейс реализуется в любом количестве вспомогательных классов, по одному для каждого порядка сортировки (на основе дружественного имени, идентификатора автомобиля и т.д.). В настоящий момент типу Car уже известно, как сравнивать автомобили друг с другом по внутреннему идентификатору. Следовательно, чтобы позволить пользователю объекта сортировать массив объектов Car по дружественному имени, потребуется создать дополнительный вспомогательный класс, реализующий интерфейс IComparer. Вот необходимый код (не забудьте импортировать в файл кода пространство имен System.Collections):