Пример 2 . Сортировка и фильтрация
Рассматриваем набор продуктов. Задача состоит в том, чтобы отсортировать их по имени и найти самые дорогие товары.
Реализация (С# 1). Сортировка по названию
Используем метод ArrayList.Sort, который обеспечивает реализацию интерфейсаICompare.
Семантическая и синтаксическая конструкция в коде программы, используемая для специфицирования услуг, предоставляемых классом или компонентом.
Тип Product может реализовывать интерфейс IComparable, но в этом случае можно будет указать только один порядок сортировки. Поэтому отдельно будет записан интерфейс IComparer, который будет применятся для сортировки.
using System.Collections;
class ProductNameComparer:IComparer // интерфейс
{ //обязательно должен содержатьфункцию сравнения
public int Compare(object x, object y)
{
Product first = (Product)x;
Product second = (Product)y;
return first.Name.CompareTo(second.Name);
}
}
static void Main(string[] args)
{
ArrayList list = Product.GetSampleProducts();
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.WriteLine();
list.Sort(new ProductNameComparer());
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.Read();
}
Ограничения/недостатки:
Необходимо определить дополнительный тип, помогающий в сортировке.
В методе Compareвынуждены использовать приведение типов (cast) при преобразовании типаobjectвProduct.
В переборе foreachтакже присутствует неявное преобразование типов, что при такой организации списка может привести к ошибкам.
Реализация (С# 2). Сортировка List<Product> с использованием интерфейса IComparer <Product>
using System.Collections.Generic;
class ProductNameComparer:IComparer<Product>
{
public int Compare(Product x, Product y)
{
return x.Name.CompareTo(y.Name);
}
}
static void Main(string[] args)
{
List<Product> list = Product.GetSampleProducts();
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.WriteLine();
list.Sort(new ProductNameComparer());
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.Read();
}
Код для компаратора упрощен. В принципе его можно заменить анонимным методом.
list.Sort(delegate(Product x, Product y)
{ return x.Name.CompareTo(y.Name);}
);
Реализация (С# 3). Сортировка списка с использованием делегата Comparison <Product>
Создается экземпляр делегата, который передается методу Sortдля выполнения сравнения.
static void Main(string[] args)
{
List<Product> list = Product.GetSampleProducts();
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.WriteLine();
list.Sort(delegate(Product x, Product y)
{
return x.Name.CompareTo(y.Name);
}
);
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.Read();
}
Реализация (С# 3 V2). Сортировка списка с использованием делегата Comparison <Product> из лямбда-выражения
Создание делегата с использованием особого вида синтаксиса (лямбда-выражения)
static void Main(string[] args)
{
List<Product> list = Product.GetSampleProducts();
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.WriteLine();
list.Sort((x,y)=>x.Name.CompareTo(y.Name));
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.Read();
}
Реализация (С# 3 V3). Сортировка списка с использованием метода расширения
Список не сортируется «на месте», а лишь возвращается в качестве результата содержимое списка в указанном порядке. Вызов метода OrderByвозможен благодаря наличию метода расширения.
using System.Linq;
static void Main(string[] args)
{
List<Product> list = Product.GetSampleProducts();
foreach (Product product in list)
Console.WriteLine(product.ToString());
Console.WriteLine();
foreach (Product product in list.OrderBy(p=>p.Name))
Console.WriteLine(product.ToString());
Console.Read();
}
Эволюция:
Слабо типизированный компаратор; нет возможности использовать делегат для сортировки
Строго типизированный компаратор; делегат сравнения
Лямбда-выражения; методы расширения; возможность не изменять список