using System.Linq;

Console.WriteLine("***** LINQ Return Values *****\n");

IEnumerable subset = GetStringSubset();

foreach (string item in subset)

{

  Console.WriteLine(item);

}

Console.ReadLine();

static IEnumerable GetStringSubset()

{

  string[] colors = {"Light Red", "Green", "Yellow", "Dark Red", "Red", "Purple"};

  // Обратите внимание, что subset является

  // совместимым с IEnumerable объектом.

  IEnumerable theRedColors =

     from c in colors where c.Contains("Red") select c;

  return theRedColors;

}

Результат выглядит вполне ожидаемо:

Light Red

Dark Red

Red

<p id="AutBody_Root495">Возвращение результатов LINQ посредством немедленного выполнения</p>

Рассмотренный пример работает ожидаемым образом только потому, что возвращаемое значение GetStringSubset() и запрос LINQ внутри этого метода были строго типизированными. Если применить ключевое слово var для определения переменной subset, то возвращать значение будет разрешено, только если метод по-прежнему прототипирован с возвращаемым типом IEnumerable (и если неявно типизированная локальная переменная на самом деле совместима с указанным возвращаемым типом).

Поскольку оперировать с типом IEnumerable несколько неудобно, можно задействовать немедленное выполнение. Скажем, вместо возвращения IEnumerable можно было бы возвратить просто string[] при условии трансформации последовательности в строго типизированный массив. Именно такое действие выполняет новый метод класса Program:

static string[] GetStringSubsetAsArray()

{

  string[] colors = {"Light Red", "Green",

                     "Yellow", "Dark Red", "Red", "Purple"};

  var theRedColors = from c in colors where c.Contains("Red") select c;

  // Отобразить результаты в массив.

  return theRedColors.ToArray();

}

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

foreach (string item in GetStringSubsetAsArray())

{

  Console.WriteLine(item);

}

Немедленное выполнение также важно при попытке возвратить вызывающему коду результаты проецирования LINQ. Мы исследуем эту тему чуть позже в главе. А сейчас давайте посмотрим, как применять запросы LINQ к обобщенным и необобщенным объектам коллекций.

<p id="AutBody_Root496">Применение запросов LINQ к объектам коллекций</p>

Помимо извлечения результатов из простого массива данных выражения запросов LINQ могут также манипулировать данными внутри классов из пространства имен System.Collections.Generic, таких как List. Создайте новый проект консольного приложения по имени ListOverCollections и определите базовый класс Car, который поддерживает текущую скорость, цвет, производителя и дружественное имя:

namespace LinqOverCollections

{

  class Car

  {

    public string PetName {get; set;} = "";

    public string Color {get; set;} = "";

    public int Speed {get; set;}

    public string Make {get; set;} = "";

  }

}

Теперь определите внутри операторов верхнего уровня локальную переменную типа List для хранения элементов типа Car и с помощью синтаксиса инициализации объектов заполните список несколькими новыми объектами Car:

using System;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using LinqOverCollections;

Console.WriteLine("***** LINQ over Generic Collections *****\n");

// Создать список List<> объектов Car.

List myCars = new List() {

  new Car{ PetName = "Henry", Color = "Silver", Speed = 100, Make = "BMW"},

  new Car{ PetName = "Daisy", Color = "Tan", Speed = 90, Make = "BMW"},

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

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