new Car{ PetName = "Mary", Color = "Black", Speed = 55, Make = "VW"},

  new Car{ PetName = "Clunker", Color = "Rust", Speed = 5, Make = "Yugo"},

  new Car{ PetName = "Melvin", Color = "White", Speed = 43, Make = "Ford"}

};

Console.ReadLine();

<p id="AutBody_Root497">Доступ к содержащимся в контейнере подобъектам</p>

Применение запроса LINQ к обобщенному контейнеру ничем не отличается от такого же действия в отношении простого массива, потому что LINQ to Objects может использоваться с любым типом, реализующим интерфейс IEnumerable. На этот раз цель заключается в построении выражения запроса для выборки из списка myCars только тех объектов Car, у которых значение скорости больше 55.

После получения подмножества на консоль будет выведено имя каждого объекта Car за счет обращения к его свойству PetName. Предположим, что определен следующий вспомогательный метод (принимающий параметр List), который вызывается в операторах верхнего уровня:

static void GetFastCars(List myCars)

{

  // Найти в List<> все объекты Car, у которых значение Speed больше 55.

  var fastCars = from c in myCars where c.Speed > 55 select c;

  foreach (var car in fastCars)

  {

    Console.WriteLine("{0} is going too fast!", car.PetName);

  }

}

Обратите внимание, что выражение запроса захватывает из List только те элементы, у которых значение Speed больше 55. Запустив приложение, вы увидите, что критерию поиска отвечают только два элемента — Нenry и Daisy.

Чтобы построить более сложный запрос, можно искать только автомобили марки BMW со значением Speed больше 90. Для этого нужно просто создать составной булевский оператор с применением операции && языка С#:

static void GetFastBMWs(List myCars)

  {

  // Найти быстрые автомобили BMW!

  var fastCars = from c in myCars

      where c.Speed > 90 && c.Make == "BMW" select c;

  foreach (var car in fastCars)

  {

    Console.WriteLine("{0} is going too fast!", car.PetName);

  }

}

Теперь выводится только одно имя Henry

<p id="AutBody_Root498">Применение запросов LINQ к необобщенным коллекциям</p>

Вспомните, что операции запросов LINQ спроектированы для работы с любым типом, реализующим интерфейс IEnumerable (как напрямую, так и через расширяющие методы). Учитывая то, что класс System.Array оснащен всей необходимой инфраструктурой, может оказаться сюрпризом, что унаследованные (необобщенные) контейнеры в пространстве имен System.Collections такой поддержкой не обладают. К счастью, итерация по данным, содержащимся внутри необобщенных коллекций, по-прежнему возможна с использованием обобщенного расширяющего метода Enumerable.OfТуре<Т>().

При вызове метода OfТуре<Т>() на объекте необобщенной коллекции (наподобие ArrayList) нужно просто указать тип элемента внутри контейнера, чтобы извлечь совместимый с IEnumerable объект. Сохранить этот элемент данных в коде можно посредством неявно типизированной переменной.

Взгляните на показанный ниже новый метод, который заполняет ArrayList набором объектов Car (не забудьте импортировать пространство имен System.Collections в начале файла Program.cs):

static void LINQOverArrayList()

{

  Console.WriteLine("***** LINQ over ArrayList *****");

  // Необобщенная коллекция объектов Car.

  ArrayList myCars = new ArrayList() {

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

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

    new Car{ PetName = "Mary", Color = "Black", Speed = 55, Make = "VW"},

    new Car{ PetName = "Clunker", Color = "Rust", Speed = 5, Make = "Yugo"},

    new Car{ PetName = "Melvin", Color = "White", Speed = 43, Make = "Ford"}

  };

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

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