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();
Доступ к содержащимся в контейнере подобъектам
Применение запроса LINQ к обобщенному контейнеру ничем не отличается от такого же действия в отношении простого массива, потому что LINQ to Objects может использоваться с любым типом, реализующим интерфейс IEnumerable. На этот раз цель заключается в построении выражения запроса для выборки из списка myCars только тех объектов Car, у которых значение скорости больше 55.
После получения подмножества на консоль будет выведено имя каждого объекта Car за счет обращения к его свойству PetName. Предположим, что определен следующий вспомогательный метод (принимающий параметр List), который вызывается в операторах верхнего уровня:
static void GetFastCars(List
{
// Найти в 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
{
// Найти быстрые автомобили 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.
Применение запросов LINQ к необобщенным коллекциям
Вспомните, что операции запросов 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"}
};