Язык программирования C#9 и платформа .NET5
Применение запросов LINQ к объектам коллекций
Помимо извлечения результатов из простого массива данных выражения запросов LINQ могут также манипулировать данными внутри классов из пространства имен
, таких какSystem.Collections.Generic. Создайте новый проект консольного приложения по имениList<T>и определите базовый классListOverCollections, который поддерживает текущую скорость, цвет, производителя и дружественное имя:Carnamespace LinqOverCollections{class Car{public string PetName {get; set;} = "";public string Color {get; set;} = "";public int Speed {get; set;}public string Make {get; set;} = "";}}Теперь определите внутри операторов верхнего уровня локальную переменную типа
для хранения элементов типаList<T>и с помощью синтаксиса инициализации объектов заполните список несколькими новыми объектамиCar:Carusing System;using System.Collections;using System.Collections.Generic;using System.Linq;using LinqOverCollections;Console.WriteLine("***** LINQ over Generic Collections *****\n");// Создать список List<> объектов Car.List<Car> myCars = new List<Car>() {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"}};Console.ReadLine();Доступ к содержащимся в контейнере подобъектам
Применение запроса LINQ к обобщенному контейнеру ничем не отличается от такого же действия в отношении простого массива, потому что LINQ to Objects может использоваться с любым типом, реализующим интерфейс
. На этот раз цель заключается в построении выражения запроса для выборки из спискаIEnumerable<T>только тех объектовmyCars, у которых значение скорости большеCar.55После получения подмножества на консоль будет выведено имя каждого объекта
за счет обращения к его свойствуCar. Предположим, что определен следующий вспомогательный метод (принимающий параметрPetName), который вызывается в операторах верхнего уровня:List<Car>static void GetFastCars(List<Car> 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<T>большеSpeed. Запустив приложение, вы увидите, что критерию поиска отвечают только два элемента —55иНenry.DaisyЧтобы построить более сложный запрос, можно искать только автомобили марки BMW со значением
большеSpeed. Для этого нужно просто создать составной булевский оператор с применением операции90языка С#:&&static void GetFastBMWs(List<Car> myCars){// Найти быстрые автомобили BMW!var fastCars = from c in myCarswhere 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<T>оснащен всей необходимой инфраструктурой, может оказаться сюрпризом, что унаследованные (необобщенные) контейнеры в пространстве именSystem.Arrayтакой поддержкой не обладают. К счастью, итерация по данным, содержащимся внутри необобщенных коллекций, по-прежнему возможна с использованием обобщенного расширяющего методаSystem.Collections.Enumerable.OfТуре<Т>()