int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };

    // Получить первый элемент в порядке последовательности

    int number = (from i in numbers select i).First();

    Console.WriteLine("First is {0}", number);

    // Получить первый элемент в порядке запроса

    number = (from i in numbers orderby i select i).First();

    Console.WriteLine("First is {0}", number);

    // Получить один элемент, который соответствует запросу

    number = (from i in numbers where i > 30 select i).Single();

    Console.WriteLine("Single is {0}", number);

    try

    {

        // В случае возвращения более одного элемента генерируется исключение

        number = (from i in numbers where i > 10 select i).Single();

    }

    catch (Exception ex)

    {

        Console.WriteLine("An exception occurred: {0}", ex.Message);

    }

  // Получить данные НЕМЕДЛЕННО как int[].

  int[] subsetAsIntArray =

    (from i in numbers where i < 10 select i).ToArray();

  // Получить данные НЕМЕДЛЕННО как List.

  List subsetAsListOfInts =

    (from i in numbers where i < 10 select i).ToList();

}

Обратите внимание, что для вызова методов Enumerable выражение LINQ целиком помещено в круглые скобки с целью приведения к корректному внутреннему типу (каким бы он ни был).

Вспомните из главы 10, что если компилятор C# в состоянии однозначно определить параметр типа обобщенного элемента, то вы не обязаны указывать этот параметр типа. Следовательно, ТоArray<Т>() (или ToList()) можно было бы вызвать так:

int[] subsetAsIntArray =

  (from i in numbers where i < 10 select i).ToArray();

Полезность немедленного выполнения очевидна, когда нужно возвратить результаты запроса LINQ внешнему вызывающему коду, что и будет темой следующего раздела главы.

<p id="AutBody_Root494">Возвращение результатов запроса LINQ</p>

Внутри класса (или структуры) можно определить поле, значением которого будет результат запроса LINQ. Однако для этого нельзя использовать неявную типизацию (т.к. ключевое слово var не может применяться к полям), и целью запроса LINQ не могут быть данные уровня экземпляра, а потому он должен быть статическим. С учетом указанных ограничений необходимость в написании кода следующего вида будет возникать редко:

class LINQBasedFieldsAreClunky

{

  private static string[] currentVideoGames =

    {"Morrowind", "Uncharted 2",

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

  // Здесь нельзя использовать неявную типизацию!

  // Тип subset должен быть известен!

  private IEnumerable subset =

    from g in currentVideoGames

    where g.Contains(" ")

    orderby g

    select g;

  public void PrintGames()

  {

    foreach (var item in subset)

    {

      Console.WriteLine(item);

    }

  }

}

Запросы LINQ часто определяются внутри области действия метода или свойства. Кроме того, для упрощения программирования результирующий набор будет храниться в неявно типизированной локальной переменной, использующей ключевое слово var. Вспомните из главы 3, что неявно типизированные переменные не могут применяться для определения параметров, возвращаемых значений, а также полей класса или структуры.

Итак, вполне вероятно, вас интересует, каким образом возвратить результат запроса внешнему коду. Ответ: в зависимости от обстоятельств. Если у вас есть результирующий набор, состоящий из строго типизированных данных, такой как массив строк или список List объектов Car, тогда вы могли бы отказаться от использования ключевого слова var и указать подходящий тип IEnumerable либо IEnumerable (т.к. IEnumerable расширяет IEnumerable). Ниже приведен пример класса Program в новом проекте консольного приложения по имени LinqRetValues:

using System;

using System.Collections.Generic;

Перейти на страницу:

Похожие книги