Секреты LINQ. Автогенерируемые свойства. Инициализаторы объектов и коллекций, страница 21

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 (операция).