Практическое руководство. Создание запросов LINQ на языке C#

В этом разделе рассматриваются три способа создания запросов LINQ на языке C#.

  1. Использование синтаксиса запроса.

  2. Использование синтаксиса метода.

  3. Использование сочетания синтаксиса запроса и синтаксиса метода.

В следующем примере демонстрируются простые запросы 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<T>. Все эти запросы можно написать с помощью 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<T>. Сам метод должен использовать 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#)

Другие ресурсы

LINQ