Console.WriteLine("Here is the ordered set of cars:");
foreach(Car c in myAutos)
{
Console.WriteLine("{0} {1}", c.CarID, c.PetName);
}
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):
using System;
using System.Collections;
namespace ComparableCar
{
// Этот вспомогательный класс используется для сортировки
// массива объектов Car по дружественному имени.
public class PetNameComparer : IComparer
{
// Проверить дружественное имя каждого объекта.
int IComparer.Compare(object o1, object o2)
{
if (o1 is Car t1 && o2 is Car t2)
{
return string.Compare(t1.PetName, t2.PetName,
StringComparison.OrdinalIgnoreCase);
}
else
{
throw new ArgumentException("Parameter is not a Car!");
// Параметр не является объектом типа Car!
}
}
}
}
Вспомогательный класс PetNameComparer может быть задействован в коде. Класс System.Array содержит несколько перегруженных версий метода Sort(), одна из которых принимает объект, реализующий интерфейс IComparer:
...
// Теперь сортировать по дружественному имени.
Array.Sort(myAutos, new PetNameComparer());
// Вывести отсортированный массив.
Console.WriteLine("Ordering by pet name:");
foreach(Car c in myAutos)
{
Console.WriteLine("{0} {1}", c.CarID, c.PetName);
}
...
Специальные свойства и специальные типы сортировки
Важно отметить, что вы можете применять специальное статическое свойство, оказывая пользователю объекта помощь с сортировкой типов Car по специфичному элементу данных. Предположим, что в класс Car добавлено статическое свойство только для чтения по имени SortByPetName, которое возвращает экземпляр класса, реализующего интерфейс IComparer (в этом случае PetNameComparer; не забудьте импортировать пространство имен System.Collections):