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

ЖАНРЫ

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

Выполнение рефлексии результирующего набора LINQ

А теперь определите в классе

Program
дополнительный вспомогательный метод по имени
ReflectOverQueryResults
, который выводит на консоль разнообразные детали о результирующем наборе LINQ (обратите внимание на параметр типа
System.Object
, позволяющий учитывать множество типов результирующих наборов):

static void ReflectOverQueryResults(object resultSet,

string queryType = "Query Expressions")

{

Console.WriteLine($"***** Info about your query using {queryType} *****");

//
Вывести тип результирующего набора

Console.WriteLine("resultSet is of type: {0}", resultSet.GetType.Name);

// Вывести местоположение результирующего набора

Console.WriteLine("resultSet location: {0}",

resultSet.GetType.Assembly.GetName.Name);

}

Модифицируйте код метода

QueryOverStrings
следующим образом:

// Построить выражение запроса для поиска

// в массиве элементов, содержащих пробел.

IEnumerable<string> subset =
from g in currentVideoGames

where g.Contains(" ")
orderby g
select g;

ReflectOverQueryResults(subset);

// Вывести результаты.

foreach (string s in subset)

{

Console.WriteLine("Item: {0}", s);

}

Запустив приложение, легко заметить, что переменная

subset
в действительности представляет собой экземпляр обобщенного типа
OrderedEnumerable<TElement, ТКеу>
(представленного в коде CIL как
OrderedEnumerable`2
), который является внутренним абстрактным типом, находящимся в сборке
System.Linq.dll
:

***** Info about your query using Query Expressions*****

resultSet is of type: OrderedEnumerable`2

resultSet location: System.Linq

Внесите такое же изменение в код метода

QueryOverStringsWithExtensionMethods
, но передав во втором параметре строку "
Extension Methods
":

// Построить выражение запроса для поиска

// в массиве элементов, содержащих пробел.

IEnumerable<string> subset =
currentVideoGames

.Where(g => g.Contains(" "))
.OrderBy(g => g)
.Select(g => g);

ReflectOverQueryResults(subset,"Extension Methods");

// Вывести результаты.

foreach (string s in subset)

{

Console.WriteLine("Item: {0}", s);

}

После

запуска приложения выяснится, что переменная
subset
является экземпляром типа
SelectIPartitionIterator
. Но если удалить из запроса конструкцию
Select(g=>g)
, то
subset
снова станет экземпляром типа
OrderedEnumerable<TElement, ТКеу>
. Что все это значит? Для подавляющего большинства разработчиков немногое (если вообще что-либо). Оба типа являются производными от
IEnumerable<T>
, проход по ним осуществляется одинаковым образом и они оба способны создавать список или массив своих значений.

***** Info about your query using Extension Methods *****

resultSet is of type: SelectIPartitionIterator`2

resultSet location: System.Linq

LINQ и неявно типизированные локальные переменные

Хотя в приведенной программе относительно легко выяснить, что результирующий набор может быть интерпретирован как перечисление объектов

string
(например,
IEnumerable<string>
), тот факт, что подмножество на самом деле имеет тип
OrderedEnumerable<TElement, ТКеу>
, не настолько ясен.

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

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

Program
:

static void QueryOverInts

{

int[] numbers = {10, 20, 30, 40, 1, 2, 3, 8};

// Вывести только элементы меньше 10.

IEnumerable<int> subset = from i in numbers where i < 10 select i;

foreach (int i in subset)

{

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

}

ReflectOverQueryResults(subset);

}

В рассматриваемом случае переменная

subset
имеет совершенно другой внутренний тип. На этот раз тип, реализующий интерфейс
IEnumerable<int>
, представляет собой низкоуровневый класс по имени
WhereArrayIterator<T>
:

Item: 1

Item: 2

Item: 3

Item: 8

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