Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Выражения запросов
Выражения запросов используют декларативный синтаксис, аналогичный SQL или XQuery, для запроса по System.Collections.Generic.IEnumerable<T> коллекциям. Во время компиляции синтаксис запроса преобразуется в вызовы методов, реализованных провайдером LINQ, который использует стандартные методы запроса. Приложения управляют стандартными операторами запросов, имеющими область видимости, указывая соответствующее пространство имен с помощью директивы using
. Следующее выражение запроса принимает массив строк, группирует их в соответствии с первым символом в строке и упорядочивает группы.
var query = from str in stringArray
group str by str[0] into stringGroup
orderby stringGroup.Key
select stringGroup;
Неявно типизированные переменные (var)
Модификатор var можно использовать для указания компилятору выводить и назначать тип, как показано ниже:
var number = 5;
var name = "Virginia";
var query = from str in stringArray
where str[0] == 'm'
select str;
Переменные, объявленные как var
, являются строго типизированными, так же как и переменные, тип которых указывается явно. Использование var
позволяет создавать анонимные типы, но только для локальных переменных. Дополнительные сведения см. в разделе Неявно типизированные локальные переменные.
Инициализаторы объектов и коллекций
Инициализаторы объектов и коллекции позволяют инициализировать объекты без явного вызова конструктора для объекта. Инициализаторы обычно используются в выражениях запросов, когда они проектируют исходные данные в новый тип данных. Предположим, есть класс с именем Customer
, имеющий публичные свойства Name
и Phone
. Инициализатор объектов можно использовать, как показано в следующем коде:
var cust = new Customer { Name = "Mike", Phone = "555-1212" };
Продолжая работу с Customer
классом, предположим, что существует источник данных, называемый IncomingOrders
, и что для каждого заказа с большим значением OrderSize
вы хотите создать новый Customer
, основанный на этом заказе. Запрос LINQ можно выполнить в этом источнике данных и использовать инициализацию объектов для заполнения коллекции:
var newLargeOrderCustomers = from o in IncomingOrders
where o.OrderSize > 5
select new Customer { Name = o.Name, Phone = o.Phone };
Источник данных может иметь больше свойств, определенных, чем Customer
класс, например OrderSize
, но при инициализации объектов данные, возвращаемые из запроса, формируются в нужный тип данных; вы выбираете данные, относящиеся к классу. В результате у вас теперь есть System.Collections.Generic.IEnumerable<T>, заполненный новыми Customer
, которые вы хотели. Предыдущий пример также можно записать в синтаксисе метода LINQ:
var newLargeOrderCustomers = IncomingOrders.Where(x => x.OrderSize > 5).Select(y => new Customer { Name = y.Name, Phone = y.Phone });
Начиная с C# 12, можно использовать выражение коллекции для инициализации коллекции.
Дополнительные сведения можно найти здесь
Анонимные типы
Компилятор создает анонимный тип. Имя типа доступно только компилятору. Анонимные типы предоставляют удобный способ группировать набор свойств временно в результате запроса, не определяя отдельный именованный тип. Анонимные типы инициализированы с новым выражением и инициализатором объектов, как показано ниже:
select new {name = cust.Name, phone = cust.Phone};
Начиная с C# 7, можно использовать кортежи для создания неименованных типов.
Методы расширения
Метод расширения — это статический метод, который может быть связан с типом, чтобы его можно было вызывать, как если бы он был методом экземпляра в типе. Эта функция позволяет добавлять новые методы в существующие типы, не изменяя их. Стандартные операторы запросов — это набор методов расширения, которые предоставляют функциональные возможности запроса LINQ для любого типа, реализующего IEnumerable<T>.
Лямбда-выражения
Лямбда-выражения — это встроенная функция, которая использует =>
оператор для разделения входных параметров из текста функции и может быть преобразована во время компиляции в делегат или дерево выражений. При программировании LINQ при выполнении прямых вызовов методов к стандартным операторам запросов возникают лямбда-выражения.
Выражения в виде данных
Объекты запросов являются компонуемыми, то есть можно возвращать запрос из метода. Объекты, представляющие запросы, не хранят полученную коллекцию, а сохраняют этапы для получения результатов при необходимости. Преимущество возврата объектов запроса из методов заключается в том, что их можно дополнительно создать или изменить. Поэтому любое возвращаемое значение или out
параметр метода, возвращающего запрос, также должно иметь этот тип. Если метод материализует запрос в конкретный List<T> или Array тип, он возвращает результаты запроса вместо самого запроса. Переменная запроса, возвращаемая из метода, по-прежнему может быть составлена или изменена.
В следующем примере первый метод QueryMethod1
возвращает запрос в качестве возвращаемого значения, а второй метод QueryMethod2
возвращает запрос в качестве out
параметра (returnQ
в примере). В обоих случаях это возвращаемый запрос, а не результаты запроса.
IEnumerable<string> QueryMethod1(int[] ints) =>
from i in ints
where i > 4
select i.ToString();
void QueryMethod2(int[] ints, out IEnumerable<string> returnQ) =>
returnQ = from i in ints
where i < 4
select i.ToString();
int[] nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var myQuery1 = QueryMethod1(nums);
Запрос myQuery1
выполняется в следующем цикле foreach.
foreach (var s in myQuery1)
{
Console.WriteLine(s);
}
Наведите указатель мыши на myQuery1
, чтобы просмотреть его тип.
Вы также можете выполнить запрос, напрямую возвращаемый QueryMethod1
, без использования myQuery1
.
foreach (var s in QueryMethod1(nums))
{
Console.WriteLine(s);
}
Наведите указатель мыши на элемент QueryMethod1
, чтобы увидеть его тип возвращаемого значения.
QueryMethod2
возвращает запрос в качестве значения параметра out
:
QueryMethod2(nums, out IEnumerable<string> myQuery2);
// Execute the returned query.
foreach (var s in myQuery2)
{
Console.WriteLine(s);
}
Запрос можно изменить с помощью композиции запросов. В этом случае предыдущий объект запроса используется для создания нового объекта запроса. Этот новый объект возвращает результаты, отличные от исходного объекта запроса.
myQuery1 = from item in myQuery1
orderby item descending
select item;
// Execute the modified query.
Console.WriteLine("\nResults of executing modified myQuery1:");
foreach (var s in myQuery1)
{
Console.WriteLine(s);
}