Console.WriteLine("Item: {0}", s);
}
}
Console.WriteLine();
}
Несмотря на возможные пути улучшения метода QueryOverStringsLongHand(), факт остается фактом — запросы LINQ способны радикально упростить процесс извлечения новых подмножеств данных из источника. Вместо построения вложенных циклов, сложной логики if/else, временных типов данных и т.п. компилятор С# сделает всю черновую работу, как только вы создадите подходящий запрос LINQ.
Выполнение рефлексии результирующего набора 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() следующим образом:
// Построить выражение запроса для поиска
// в массиве элементов, содержащих пробел.
IEnumerablefrom g in currentVideoGames
where g.Contains(" ") orderby g select g;
ReflectOverQueryResults(subset);
// Вывести результаты.
foreach (string s in subset)
{
Console.WriteLine("Item: {0}", s);
}
Запустив приложение, легко заметить, что переменная subset в действительности представляет собой экземпляр обобщенного типа OrderedEnumerable (представленного в коде 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":
// Построить выражение запроса для поиска
// в массиве элементов, содержащих пробел.
IEnumerablecurrentVideoGames
.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. Что все это значит? Для подавляющего большинства разработчиков немногое (если вообще что-либо). Оба типа являются производными от IEnumerable, проход по ним осуществляется одинаковым образом и они оба способны создавать список или массив своих значений.
***** Info about your query using Extension Methods *****
resultSet is of type: SelectIPartitionIterator`2
resultSet location: System.Linq
LINQ и неявно типизированные локальные переменные