Практическое руководство. Создание запросов LINQ на языке C#
В этом разделе рассматриваются три способа создания запросов LINQ на языке C#.
Использование синтаксиса запроса.
Использование синтаксиса метода.
Использование сочетания синтаксиса запроса и синтаксиса метода.
В следующем примере демонстрируются простые запросы LINQ при использовании каждого из перечисленных выше синтаксисов. Общее правило таково: следует использовать (1) всегда, когда это возможно; (2) и (3) при необходимости.
Примечание
Эти запросы работают с простыми коллекциями в памяти, однако базовый синтаксис идентичен синтаксису, использованному в LINQ to SQL и LINQ to XML.
Пример
Синтаксис запроса
Лучше всего для создания запросов использовать синтаксис запроса, создавая выражения запросов. В следующем примере показано три выражения запроса. В первом выражении демонстрируется фильтрация или ограничение результатов путем применения условий в предложении where. Оно возвращает все элементы в исходной последовательности со значениями больше 7 и меньше 3. Второе выражение демонстрирует сортировку возвращаемых результатов. Третий запрос демонстрирует группировку результатов. Он возвращает две группы на основе первой буквы слова.
// Query #1.
List<int> numbers = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
// The query variable can also be implicitly typed by using var
IEnumerable<int> filteringQuery =
from num in numbers
where num < 3 || num > 7
select num;
// Query #2.
IEnumerable<int> orderingQuery =
from num in numbers
where num < 3 || num > 7
orderby num ascending
select num;
// Query #3.
string[] groupingQuery = { "carrots", "cabbage", "broccoli", "beans", "barley" };
IEnumerable<IGrouping<char, string>> queryFoodGroups =
from item in groupingQuery
group item by item[0];
Обратите внимание, что тип запросов — IEnumerable. Все эти запросы можно написать с помощью var, как показано в примере ниже.
var query = from num in numbers...
В каждом из приведенных выше примеров фактическое выполнение запроса откладывается до использования переменной запроса в операторе foreach. Дополнительные сведения см. в разделе Введение в запросы LINQ (C#).
Синтаксис метода
Некоторые операции запросов должны быть выражены в виде вызова метода. Чаще всего используются методы, возвращающие одноэлементные числовые значения, например Sum, Max, Min, Average и т.д. Эти методы всегда должны быть вызваны последними в запросе, поскольку они представляют только одно значение и не могут служить источником дополнительных действий запроса. В следующем примере демонстрируется вызов метода в выражении запроса.
List<int> numbers1 = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
List<int> numbers2 = new List<int>() { 15, 14, 11, 13, 19, 18, 16, 17, 12, 10 };
// Query #4.
double average = numbers1.Average();
// Query #5.
IEnumerable<int> concatenationQuery = numbers1.Concat(numbers2);
Если у метода есть параметры, они представлены в виде лямбда-выражения, как показано в следующем примере.
// Query #6.
IEnumerable<int> largeNumbersQuery = numbers2.Where(c => c > 15);
В предыдущих запросах только запрос №4 выполнялся немедленно. Причина заключается в том, что он возвращает одиночное значение, а не универсальную коллекцию IEnumerable. Сам метод должен использовать foreach для вычисления значения.
Любой их перечисленных ранее запросов можно написать с использованием неявной типизации с помощью var, как показано в следующем примере.
// var is used for convenience in these queries
var average = numbers1.Average();
var concatenationQuery = numbers1.Concat(numbers2);
var largeNumbersQuery = numbers2.Where(c => c > 15);
Смешанный синтаксис запроса и метода
В этом примере демонстрируется использование синтаксиса метода для результатов предложения запроса. Нужно всего лишь заключить выражение запроса в скобки, а затем применить оператор точки и вызвать метод. В следующем примере запрос #7 возвращает количество чисел, значение которых лежит в диапазоне от 3 до 7. Однако в общем случае лучше использовать вторую переменную для хранения результатов вызова метода. Таким образом, будет меньше вероятность перепутать запрос с результатами запроса.
// Query #7.
// Using a query expression with method syntax
int numCount1 =
(from num in numbers1
where num < 3 || num > 7
select num).Count();
// Better: Create a new variable to store
// the method call result
IEnumerable<int> numbersQuery =
from num in numbers1
where num < 3 || num > 7
select num;
int numCount2 = numbersQuery.Count();
Запрос №7 возвращает одиночное значение, а не коллекцию, поэтому он выполняется мгновенно.
Предыдущий запрос можно написать с использованием неявной типизации с помощью var, как показано в следующем примере:
var numCount = (from num in numbers...
Можно использовать синтаксис метода следующим образом.
var numCount = numbers.Where(n => n < 3 || n > 7).Count();
Можно использовать явную типизацию следующим образом.
int numCount = numbers.Where(n => n < 3 || n > 7).Count();
См. также
Задачи
Пошаговое руководство. Написание запросов на C# (LINQ)
Ссылки
Предложение where (Справочник по C#)
Основные понятия
Выражения запросов LINQ (Руководство по программированию на C#)