q = personList.OrderBy (c => c, new NameComparer());
Console.WriteLine("\nPersons ordered by Name, Age, Status:");
foreach (var p in q)
Console.WriteLine("{0} {1} {2}", p.Name.PadRight(7), p.Birth.ToShortDateString(), p.Status);
q = personList.OrderBy (c => c, new AgeComparer());
Console.WriteLine("\nPersons ordered by Age, Name, Status:");
. . . . .
Результат, полученный с помощью любого из классов *Comparer, можно получить и другим способом. Например, с помощью вызова метода OrderBy, а затем двухкратного вызова extension-метода ThenBy.
q = personList.OrderBy(c=>c.Status).ThenBy(c=>c.Name).ThenBy(c=>c.Birth);
Также просмотрите справку по методу ThenByDescending.
Рассмотрим extension-метод Aggregate, который применяет аккумулирующую функцию для всех элементов какой-либо последовательности.
double[] doubles = { 1, 2, 3, 4, 5 };
double product = doubles.Aggregate((a, b) => a * b);
Console.WriteLine ("5!: " + product);
Этот фрагмент вычислит и выведет факториал числа 5, так как в качестве аккумулирующей функции задано λ-выражение, которое перемножает два соседних элемента.
Здесь использована одна из версий метода Aggregate (с одним параметром). Она перемещает шаблон (a, b) вдоль всей последовательности (в нашем случае, массива doubles), применяет к текущей паре элементов подстановку (a*b) и аккумулирует результат в переменной product. Другие версии метода Aggregate требуют задать большее количество параметров, и позволяют выполнить более сложные манипуляции с элементами последовательности. Например:
double sum = 10000;
int[] withdrawals = { 2000, 1000, 4000, 5000 };
double res = withdrawals.Aggregate(sum, (b, s) => s <= b ? b - s : b);
Console.WriteLine("Ending balance: {0}", res);
¨ Массив withdrawals описывает последовательность попыток снятия денег с банковского счета.
¨ λ-выражение, определяющее аккумулирующую функцию, задано так, чтобы исключить возможность снятия со счета суммы, которая превышает остаток.
¨ b — текущий баланс (остаток на счете).
¨ s — текущая попытка снять какую-то сумму денег (текущий элемент массива withdrawals).
Результат res применения метода Aggregate к коллекции withdrawals будет 3000, так как последняя попытка снять 5000 не пройдет проверки s <= b.
Рассмотрим еще несколько расширяющих методов: Union, Intersect, Except и Count. Первые три работают с парой последовательностей, а последний — с одной.
¨ Union (объединение) вычисляет множество общих элементов последовательностей,
¨ Intersect — множество пересекающихся элементов,
¨ Except — множество различий.
¨ Метод Count возвращает количество элементов в последовательности.
int[] u = { 1, 2, 3, 4, 5, 6 },
v = { 4, 5, 6, 7, 8, 9, 10 };
var both = u.Intersect(v);
Console.WriteLine("\nu.Intersect(v)");
foreach (var n in both)
Console.Write(n + ", ");
var r = both.Except(v.Intersect(u));
Console.WriteLine("\nu.Intersect(v).Except(v.Intersect(u)).Count(): " + r.Count());
Console.WriteLine("\nu.Union(v).Except(u)");
foreach (var n in u.Union(v).Except(u))
Console.Write(n + ", ");
Запустите код и убедитесь, что различий в пересечениях u.Intersect(v) и v.Intersect(u) нет, а выражение u.Union(v).Except(u) вычисляет множество элементов второй последовательности за вычетом элементов, общих для u и v.
Мы рассмотрели лишь малую часть методов-расширений для класса Enumerable, которые реализованы в пространстве имен System.Linq. Все эти методы являются основой построения интегрированных запросов, которые можно выполнять как путем прямого вызова extension methods, так и с помощью специальных синтаксических конструкций языка C#.
Рассмотрим пример, который выполняет один и тот же запрос, но использует при этом два различных подхода. В первом подходе запрос осуществляет прямой вызов метода Where, а во втором — использует новые операции языка C#: from, where и select. В документации MSDN идентификаторы операций where и select языка C# (в отличие от методов Where и Select) часто сопровождают уточняющим описателем clause (операция).
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.