Бөлісу құралы:


Возможности C#, поддерживающие LINQ

Выражения запросов

Выражения запросов используют декларативный синтаксис, аналогичный 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);
}