Рейтинговые книги
Читем онлайн Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 164 165 166 167 168 169 170 171 172 ... 407
элементов на основе определенного критерия. Возможно, требуется получить только элементы, которые содержат число (например, "System Shock 2", "Uncharted 2" и "Fallout 3"), содержат заданное количество символов либо не содержат встроенных пробелов (скажем, "Morrowind" или "Daxter"). В то время как такие задачи определенно можно решать с использованием членов типа System.Array, прикладывая приличные усилия, выражения запросов LINQ значительно упрощают процесс.

Исходя из предположения, что из массива нужно получить только элементы, содержащие внутри себя пробел, и представить их в алфавитном порядке, можно построить следующее выражение запроса LINQ:

static void QueryOverStrings()

{

  // Предположим, что имеется массив строк.

  string[] currentVideoGames = {"Morrowind", "Uncharted 2",

                                "Fallout 3", "Daxter", "System Shock 2"};

  // Построить выражение запроса для нахождения

  // элементов массива, которые содержат пробелы.

  IEnumerable<string> subset =

    from g in currentVideoGames

    where g.Contains(" ")

    orderby g

    select g;

  // Вывести результаты.

  foreach (string s in subset)

  {

    Console.WriteLine("Item: {0}", s);

  }

}

Обратите внимание, что в созданном здесь выражении запроса применяются операции from, in, where, orderby и select языка LINQ. Формальности синтаксиса выражений запросов будут подробно излагаться далее в главе. Тем не менее, даже сейчас вы в состоянии прочесть данный оператор примерно так: "предоставить мне элементы из currentVideoGames, содержащие пробелы, в алфавитном порядке".

Каждому элементу, который соответствует критерию поиска, назначается имя g (от "game"), но подошло бы любое допустимое имя переменной С#:

IEnumerable<string> subset =

  from game in currentVideoGames

  where game.Contains(" ")

  orderby game

  select game;

Возвращенная последовательность сохраняется в переменной по имени subset, которая имеет тип, реализующий обобщенную версию интерфейса IEnumerable<T>, где Т — тип System.String (в конце концов, вы запрашиваете массив элементов string). После получения результирующего набора его элементы затем просто выводятся на консоль с использованием стандартной конструкции foreach. Запустив приложение, вы получите следующий вывод:

***** Fun with LINQ to Objects *****

Item: Fallout 3

Item: System Shock 2

Item: Uncharted 2

Решение с использованием расширяющих методов

Применяемый ранее (и далее в главе) синтаксис LINQ называется выражениями запросов LINQ, которые представляют собой формат, похожий на SQL, но слегка отличающийся от него. Существует еще один синтаксис с расширяющими методами, который будет использоваться в большинстве примеров в настоящей книге. Создайте новый метод по имени QueryOverStringsWithExtensionMethods() со следующим кодом:

static void QueryOverStringsWithExtensionMethods()

{

  // Пусть имеется массив строк.

  string[] currentVideoGames = {"Morrowind", "Uncharted 2",

                                "Fallout 3", "Daxter", "System Shock 2"};

  // Построить выражение запроса для поиска

  // в массиве элементов, содержащих пробелы.

  IEnumerable<string> subset =

    currentVideoGames.Where(g => g.Contains(" "))

                           .OrderBy(g => g).Select(g => g);

  // Вывести результаты.

  foreach (string s in subset)

  {

    Console.WriteLine("Item: {0}", s);

  }

}

Код здесь тот же, что и в предыдущем методе, кроме строк, выделенных полужирным. В них демонстрируется применение синтаксиса расширяющих методов, в котором для определения операций внутри каждого метода используются лямбда-выражения. Например, лямбда-выражение в методе Where() определяет условие (содержит ли значение пробел). Как и в синтаксисе выражений запросов, используемая для идентификации значения буква произвольна; в примере применяется v для видеоигр (video game).

Хотя результаты аналогичны (метод дает такой же вывод, как и предыдущий метод, использующий выражение запроса), вскоре вы увидите, что тип результирующего набора несколько отличается. В большинстве (если фактически не во всех) сценариях подобное отличие не приводит к каким-либо проблемам и форматы могут применяться взаимозаменяемо.

Решение без использования 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();

}

Несмотря на возможные пути улучшения метода QueryOverStringsLongHand(), факт остается фактом — запросы LINQ способны радикально упростить процесс извлечения новых подмножеств данных из источника. Вместо построения вложенных циклов, сложной логики if/else, временных типов данных и т.п. компилятор С# сделает всю черновую работу, как только вы создадите подходящий запрос LINQ.

Выполнение рефлексии результирующего набора LINQ

А теперь определите в классе Program дополнительный вспомогательный метод по имени ReflectOverQueryResults(), который выводит на консоль разнообразные детали о результирующем наборе LINQ (обратите внимание на параметр типа System.Object, позволяющий учитывать множество типов результирующих наборов):

static 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);

}

Модифицируйте код метода QueryOverStrings() следующим образом:

// Построить выражение запроса для поиска

// в массиве элементов, содержащих пробел.

IEnumerable<string> subset = from g in currentVideoGames

  where g.Contains(" ") orderby g select g;

1 ... 164 165 166 167 168 169 170 171 172 ... 407
На этой странице вы можете бесплатно читать книгу Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен бесплатно.

Оставить комментарий