Ответы на все вопросы (СиППО (67-73))

Посмотреть архив целиком






67.Ламбда-выражения и их использование на LINQ

68.Две разновидности синтаксиса  на LINQ

69.Отложенное выполнение операторов на LINQ

70.Операторы Select, Where, Take, Skip, TakeWhile, SkipWhile

71.Агрегирующие функции на LINQ

72.Группировка данных на LINQ

73.Оператор соединения на LINQ





67.Ламбда-выражения и их использование на LINQ

 

Простейший запрос состоит из одной входной по­следовательности и одного оператора. Например, мы можем применить оператор where к строковому массиву и извлечь те его элементы, длина которых не меньше четырех символов. Поскольку стандартные операторы запроса реали­зованы в виде методов расширения, мы можем вы­звать Where непосредственно ДЛЯ массива names так, словно это метод экземпляра:

IEnumerable filteredNames = names."Where (n => n.Length >= 4);

Большинство операторов запроса принимает лямбда-выражение в качестве аргумента. Лямбда-выражение помогает направить и сформировать запрос. В нашем примере лямбда-выражение выглядит так:

n => п.Length >= 4

Входной аргумент соответствует входному эле­менту. В этом случае входной аргумент n пред­ставляет имя в массиве и имеет тип string. Опера­тор where требует, чтобы лямбда-выражение возвращало значение типа bool. Когда оно истин­но, элемент должен быть включен в выходную по­следовательность.

Будем называть такие запросы лямбда-запросами

Чтобы строить более сложные запросы, вы добав­ляете новые операторы, образуя цепочку. Напри­мер, в следующем запросе из массива извлекаются все строки с буквой "а", после чего они сортиру­ются по длине и переводятся в верхний регистр:

string[] names = {"Tom","Dick","Harry","Mary","Jay" }; IEnumerable query = names.Where (n => n.Contains ("a")) .OrderBy (n => n.Length) .Select (n => n.ToUpper());

foreach (string name in query)

Console.Write (name + "|");

Результат: JAY|MARY|HARRY|

Примечание        

Оператор запроса никогда не изменяет вход­ную последовательность. Вместо нее он воз­вращает новую. Это соответствует парадигме функционального программирования, из кото­рой исходит LINQ.

Когда операторы запроса выстраиваются в цепоч­ку, как в нашем примере, выходная последователь­ность одного оператора становится входной для следующего.

В предыдущих примерах мы передавали оператору where такое лямбда-выражение:

n => n.Contains ("а") // На входе строка,

// на выходе булево выражение

Предназначение лямбда-выражения зависит от конкретного оператора запроса. С оператором where оно показывает, должен ли элемент попадать в выходную последовательность. У оператора OrderBy лямбда-выражение отображает каждый элемент входной последовательности на ключ сор­тировки, а у оператора select оно определяет, как должен быть преобразован элемент из входной по­следовательности перед подачей его в выходную.

Примечание

В операторе запроса лямбда-выражение всегда относится к отдельным элементам входной по­следовательности, а не к последовательности в целом.

Вы можете относиться к лямбда-выражению как к обратному вызову. Оператор запроса вычисляет зна­чение лямбда-выражения "по требованию",— как правило, один раз для каждого элемента входной по­следовательности. Лямбда-выражения позволяют вам внести свою логику в операторы запроса. Это делает операторы запроса гибкими и в то же время просты­ми по внутреннему устройству. Приведем полную реализацию метода Enumerable.Where, опустив то, что касается обработки исключений:

public static IEnumerable Where (

this IEnumerable source,

Func predicate)

{

foreach (TSource element in source)

if (predicate (element))

yield return element;

}

Лямбда-выражения и типы элементов

В стандартных операторах запроса используются следующие имена обобщенных типов.

Обозначение обобщенного типа

Смысл

TSource

Тип элемента входной последова­тельности

TResult

Тип элемента выходной последова­тельности — отличается от

TSource

TKey

Тип ключа, используемого при сортировке, группировании или объединении

Тип TSource определяется входной последователь­ностью. Типы TResult и Tkey выводятся из вашего лямбда-выражения.



68.Две разновидности синтаксиса  на LINQ

Простейший запрос состоит из одной входной по­следовательности и одного оператора. Например, мы можем применить оператор where к строковому массиву и извлечь те его элементы, длина которых не меньше четырех символов. Поскольку стандартные операторы запроса реали­зованы в виде методов расширения, мы можем вы­звать Where непосредственно ДЛЯ массива names так, словно это метод экземпляра:

IEnumerable filteredNames = names."Where (n => n.Length >= 4);

Большинство операторов запроса принимает лямбда-выражение в качестве аргумента. Лямбда-выражение помогает направить и сформировать запрос. В нашем примере лямбда-выражение выглядит так:

n => п.Length >= 4

Входной аргумент соответствует входному эле­менту. В этом случае входной аргумент n пред­ставляет имя в массиве и имеет тип string. Опера­тор where требует, чтобы лямбда-выражение возвращало значение типа bool. Когда оно истин­но, элемент должен быть включен в выходную по­следовательность.

Будем называть такие запросы лямбда-запросами

Чтобы строить более сложные запросы, вы добав­ляете новые операторы, образуя цепочку. Напри­мер, в следующем запросе из массива извлекаются все строки с буквой "а", после чего они сортиру­ются по длине и переводятся в верхний регистр:

string[] names = {"Tom","Dick","Harry","Mary","Jay" }; IEnumerable query = names.Where (n => n.Contains ("a")) .OrderBy (n => n.Length) .Select (n => n.ToUpper());

foreach (string name in query)

Console.Write (name + "|");

//Результат: JAY|MARY|HARRY|

Вот как выглядит тот же запрос в соответст­вии с синтаксисом, облегчающим его восприятие:

string[] names = {

"Tom","Dick","Harry","Mary","Jay" };

IEnumerable query =

from n in names

where n.Contains ("a") // Фильтровать эле­менты

orderby n.Length    // Сортировать эле­менты

select n.ToUpper();    // Проецировать каж­дый элемент

foreach (string name in query)

Console.Write (name + "/");

// Результат: JAY/MARY/HARRY/

Запрос с синтаксисом, облегчающим восприятие, всегда начинается с конструкции from и заканчи­вается конструкцией либо select, либо group. Конструкция from объявляет переменную итера­ции (в данном случае n). Вы можете считать, что она используется для перебора элементов входной коллекции, аналогично оператору foreach.

Компилятор обрабатывает запросы с синтаксисом, облегчающим восприятие, переводя их в лямбда-синтаксис. Фактически это означает, что все, написанное вами в соответствии с синтакси­сом, облегчающим восприятие, могло быть написано и с соблюдением лямбда-синтаксиса. Запрос из наше­го примера транслируется в следующий код:

IEnumerable query = names .Where (n => n.Contains ("a")).OrderBy (n => n.Length).Select (n => n.ToUpper());

Затем операторы Where, OrderBy и Select будут откомпилированы по тем же правилам, что и за­просы, изначально написанные с соблюдением лямбда-синтаксиса.

Если оператор запроса не поддерживается синтак­сисом, облегчающим восприятие, вы можете ком­бинировать этот синтаксис с лямбда-синтаксисом. Единственное требование, которое при этом вы­двигается, — каждая составляющая "понятного" синтаксиса должна быть полной (то есть начинать­ся с конструкции from и заканчиваться конструк­цией select ИЛИ group).

Например:

int count =

(

from name in names

where n.Contains ("a")

select name

).Count();

Бывают ситуации, в которых запросы со смешан­ным синтаксисом оказываются самыми эффектив­ными в терминах функциональности и простоты. Избегайте оказывать предпочтение какому-то од­ному из двух вариантов синтаксиса. В противном случае вы не сможете уверенно и безошибочно пи­сать запросы в смешанном синтаксисе!

 



69.Отложенное выполнение операторов на LINQ

Важной особенностью большинства операторов запроса является тот факт, что они выполняются не тогда, когда сконструированы, а при переборе эле­ментов (то есть когда для соответствующего пере­числителя вызывается метод MoveNext):

var numbers = new List(); numbers.Add (1) ; // Построить запрос

IEnumerable query = numbers.Select (n => n * 10);

numbers.Add (2); // "Незаметно" добавить еще один элемент

foreach (int n in query)

Console.Write (n + "|");

// 10|20|

Дополнительный элемент, который мы "тайком" добавили после конструирования запроса, попадает в результат, потому что ни фильтрация, ни сорти­ровка не происходят, пока не начнет выполняться оператор foreach. Это называется отложенным или "ленивым" выполнением. Отложенное выпол­нение характерно для всех стандартных операто­ров запроса, кроме

·      операторов, возвращающих один элемент или скалярное значение, таких как First или Count;

·      операторов преобразования типа: ToArray, ToList, ToDictionary, ToLookup

Эти операторы приводят к немедленному выпол­нению запроса, потому что у возвращаемых ими результатов нет механизма, который обеспечивал бы отложенное выполнение. Например, метод Count возвращает целое число, которое затем ни­как не "перебирается". Следующий запрос выпол­няется немедленно:

int matches = numbers.Where (n => n < 2).Count(); // 1

Отложенное выполнение играет важную роль, по­тому что оно отделяет конструирование запроса от его выполнения. Это позволяет вам конструиро­вать запрос за несколько шагов, а также делать LINQ-запросы к SQL.

 



70.Операторы Select, Where, Take, Skip, TakeWhile, SkipWhile



Проецирование

Оператор Select

Аргумент

Тип

Исходная последо­вательность

IEnumerable

Селектор результата

TSource => TResult


Случайные файлы

Файл
240-2200.DOC
xistori.doc
44947.doc
96652.rtf
24432-1.rtf




Чтобы не видеть здесь видео-рекламу достаточно стать зарегистрированным пользователем.
Чтобы не видеть никакую рекламу на сайте, нужно стать VIP-пользователем.
Это можно сделать совершенно бесплатно. Читайте подробности тут.