Язык программирования C#9 и платформа .NET5
Item: System Shock 2Item: Uncharted 2Решение с использованием расширяющих методов
Применяемый ранее (и далее в главе) синтаксис LINQ называется выражениями запросов LINQ, которые представляют собой формат, похожий на SQL, но слегка отличающийся от него. Существует еще один синтаксис с расширяющими методами, который будет использоваться в большинстве примеров в настоящей книге. Создайте новый метод по имени
со следующим кодом:QueryOverStringsWithExtensionMethods()static void QueryOverStringsWithExtensionMethods(){// Пусть имеется массив строк.string[] currentVideoGames = {"Morrowind", "Uncharted 2","Fallout 3", "Daxter", "System Shock 2"};// Построить выражение запроса для поиска// в массиве элементов, содержащих пробелы.<b> IEnumerable<string> subset =</b><b> currentVideoGames.Where(g => g.Contains(" "))</b><b> .OrderBy(g => g).Select(g => g);</b>// Вывести результаты.foreach (string s in subset){Console.WriteLine("Item: {0}", s);}}Код здесь тот же, что и в предыдущем методе, кроме строк, выделенных полужирным. В них демонстрируется применение синтаксиса расширяющих методов, в котором для определения операций внутри каждого метода используются лямбда-выражения. Например, лямбда-выражение в методе
определяет условие (содержит ли значение пробел). Как и в синтаксисе выражений запросов, используемая для идентификации значения буква произвольна; в примере применяетсяWhere()для видеоигр (video game).vХотя результаты аналогичны (метод дает такой же вывод, как и предыдущий метод, использующий выражение запроса), вскоре вы увидите, что тип результирующего набора несколько отличается. В большинстве (если фактически не во всех) сценариях подобное отличие не приводит к каким-либо проблемам и форматы могут применяться взаимозаменяемо.
Решение без использования LINQ
Конечно, применение LINQ никогда не бывает обязательным. При желании идентичный результирующий набор можно получить без участия LINQ с помощью таких программных конструкций, как операторы
и циклыif. Ниже приведен метод, который выдает тот же самый результат, что иfor, но в намного более многословной манере:QueryOverStrings()static void QueryOverStringsLongHand(){// Предположим, что имеется массив строк.string[] currentVideoGames = {"Morrowind", "Uncharted 2","Fallout 3", "Daxter", "System Shock 2"};string[] gamesWithSpaces = new string[5];for (int i = 0; i < currentVideoGames.Length; i++){if (currentVideoGames[i].Contains(" ")){gamesWithSpaces[i] = currentVideoGames[i];}}// Отсортировать набор.Array.Sort(gamesWithSpaces);// Вывести результаты.foreach (string s in gamesWithSpaces){if( s != null){Console.WriteLine("Item: {0}", s);}}Console.WriteLine();}Несмотря на возможные пути улучшения метода
, факт остается фактом — запросы LINQ способны радикально упростить процесс извлечения новых подмножеств данных из источника. Вместо построения вложенных циклов, сложной логикиQueryOverStringsLongHand(), временных типов данных и т.п. компилятор С# сделает всю черновую работу, как только вы создадите подходящий запрос LINQ.if/elseВыполнение рефлексии результирующего набора LINQ
А теперь определите в классе
дополнительный вспомогательный метод по имениProgram, который выводит на консоль разнообразные детали о результирующем наборе LINQ (обратите внимание на параметр типаReflectOverQueryResults(), позволяющий учитывать множество типов результирующих наборов):System.Objectstatic void ReflectOverQueryResults(object resultSet,string queryType = "Query Expressions"){Console.WriteLine($"***** Info about your query using {queryType} *****");// Вывести тип результирующего набораConsole.WriteLine("resultSet is of type: {0}", resultSet.GetType().Name);// Вывести местоположение результирующего набораConsole.WriteLine("resultSet location: {0}",resultSet.GetType().Assembly.GetName().Name);}