Язык программирования C#9 и платформа .NET5
using System.Linq;static void QueryStringWithOperators(){Console.WriteLine("***** Using Query Operators *****");string[] currentVideoGames = {"Morrowind", "Uncharted 2","Fallout 3", "Daxter", "SystemShock 2"};var subset = from game in currentVideoGameswhere game.Contains(" ") orderby game select game;foreach (string s in subset){Console.WriteLine("Item: {0}", s);}}Очевидное преимущество использования операций запросов C# при построении выражений запросов заключается в том, что делегаты
и вызовы методовFunс<>остаются вне поля зрения и внимания, т.к. выполнение необходимой трансляции возлагается на компилятор С#. Бесспорно, создание выражений LINQ с применением различных операций запросов (Enumerable,from,inилиwhere) является наиболее распространенным и простым подходом.orderbyПостроение выражений запросов с использованием типа Enumerable и лямбда-выражений
Имейте в виду, что применяемые здесь операции запросов LINQ представляют собой сокращенные версии вызова расширяющих методов, определенных в типе
. Рассмотрим показанный ниже методEnumerable, который обрабатывает локальный массив строк, но на этот раз в нем напрямую используются расширяющие методыQueryStringsWithEnumerableAndLambdas():Enumerablestatic void QueryStringsWithEnumerableAndLambdas(){Console.WriteLine("***** Using Enumerable / Lambda Expressions *****");string[] currentVideoGames = {"Morrowind", "Uncharted 2","Fallout 3", "Daxter", "SystemShock 2"};// Построить выражение запроса с использованием расширяющих методов,// предоставленных типу Array через тип Enumerable.var subset = currentVideoGames.Where(game => game.Contains(" ")).OrderBy(game => game).Select(game => game);// Вывести результаты.foreach (var game in subset){Console.WriteLine("Item: {0}", game);}Console.WriteLine();}Здесь сначала вызывается расширяющий метод
на строковом массивеWhere(). Вспомните, что классcurrentVideoGamesполучает данный метод от классаArray. МетодEnumerableтребует параметра типа делегатаEnumerable.Where(). Первый параметр типа упомянутого делегата представляет совместимые с интерфейсомSystem.Func<T1,TResult>данные для обработки (массив строк в рассматриваемом случае), а второй — результирующие данные метода, которые получаются от единственного оператора, вставленного в лямбда-выражение.IEnumerable<T>Возвращаемое значение метода
в приведенном примере кода скрыто от глаз, но "за кулисами" работа происходит с типомWhere(). На объекте указанного типа вызывается обобщенный методOrderedEnumerable, который также принимает параметр типа делегатаOrderBy(). Теперь производится передача всех элементов по очереди посредством подходящего лямбда-выражения. Результатом вызоваFunc<>является новая упорядоченная последовательность первоначальных данных.OrderBy()И, наконец, осуществляется вызов метода
на последовательности, возвращеннойSelect(), который в итоге дает финальный набор данных, сохраняемый в неявно типизированной переменной по имениOrderBy().subsetКонечно, такой "длинный" запрос LINQ несколько сложнее для восприятия, чем предыдущий пример с операциями запросов LINQ. Без сомнения, часть сложности связана с объединением в цепочку вызовов посредством операции точки. Вот тот же самый запрос с выделением каждого шага в отдельный фрагмент (разбивать запрос на части можно разными способами):
static void QueryStringsWithEnumerableAndLambdas2(){Console.WriteLine("***** Using Enumerable / Lambda Expressions *****");string[] currentVideoGames = {"Morrowind", "Uncharted 2","Fallout 3", "Daxter", "SystemShock 2"};// Разбить на части.var gamesWithSpaces =currentVideoGames.Where(game => game.Contains(" "));var orderedGames = gamesWithSpaces.OrderBy(game => game);var subset = orderedGames.Select(game => game);foreach (var game in subset)