Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

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

При вызове метода

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

Взгляните на показанный ниже новый метод, который заполняет

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"}

};

//
Трансформировать ArrayList в тип, совместимый c IEnumerable<T>.

var myCarsEnum = myCars.OfType<Car>;

// Создать выражение запроса, нацеленное на совместимый с IEnumerable<T> тип.

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

foreach (var car in fastCars)

{

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

}

}

Аналогично предшествующим примерам этот метод, вызванный в операторах верхнего уровня, отобразит только имена

Henry
и
Daisy
, основываясь на формате запроса LINQ.

Фильтрация данных с использованием метода OfТуре<Т>

Как вы уже знаете, необобщенные типы способны содержать любые комбинации элементов, поскольку члены этих контейнеров (вроде

ArrayList
) прототипированы для приема
System.Object
. Например, предположим, что
ArrayList
содержит разные элементы, часть которых являются числовыми. Получить подмножество, состоящее только из числовых данных, можно с помощью метода
OfТуре<Т>
, т.к. во время итерации он отфильтрует элементы, тип которых отличается от заданного:

static void OfTypeAsFilter

{

// Извлечь из ArrayList целочисленные значения.

ArrayList myStuff = new ArrayList;

myStuff.AddRange(new object[] { 10, 400, 8, false, new Car, "string data" });

var myInts = myStuff.OfType<int>;

// Выводит 10, 400 и 8.

foreach (int i in myInts)

{

Console.WriteLine("Int value: {0}", i);

}

}

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

Поделиться с друзьями: