Шрифт:
Интервал:
Закладка:
class LINQBasedFieldsAreClunky
{
private static string[] currentVideoGames =
{"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
<b> // Здесь нельзя использовать неявную типизацию!</b>
<b> // Тип subset должен быть известен!</b>
private IEnumerable<string> subset =
from g in currentVideoGames
where g.Contains(" ")
orderby g
select g;
public void PrintGames()
{
foreach (var item in subset)
{
Console.WriteLine(item);
}
}
}
Запросы LINQ часто определяются внутри области действия метода или свойства. Кроме того, для упрощения программирования результирующий набор будет храниться в неявно типизированной локальной переменной, использующей ключевое слово var. Вспомните из главы 3, что неявно типизированные переменные не могут применяться для определения параметров, возвращаемых значений, а также полей класса или структуры.
Итак, вполне вероятно, вас интересует, каким образом возвратить результат запроса внешнему коду. Ответ: в зависимости от обстоятельств. Если у вас есть результирующий набор, состоящий из строго типизированных данных, такой как массив строк или список List<T> объектов Car, тогда вы могли бы отказаться от использования ключевого слова var и указать подходящий тип IEnumerable<T> либо IEnumerable (т.к. IEnumerable<T> расширяет IEnumerable). Ниже приведен пример класса Program в новом проекте консольного приложения по имени LinqRetValues:
using System;
using System.Collections.Generic;
using System.Linq;
Console.WriteLine("***** LINQ Return Values *****n");
IEnumerable<string> subset = GetStringSubset();
foreach (string item in subset)
{
Console.WriteLine(item);
}
Console.ReadLine();
static IEnumerable<string> GetStringSubset()
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390}){
string[] colors = {"Light Red", "Green", "Yellow", "Dark Red", "Red", "Purple"};
// Обратите внимание, что subset является
// совместимым с IEnumerable<string> объектом.
IEnumerable<string> theRedColors =
from c in colors where c.Contains("Red") select c;
return theRedColors;
}
Результат выглядит вполне ожидаемо:
Light Red
Dark Red
Red
Возвращение результатов LINQ посредством немедленного выполнения
Рассмотренный пример работает ожидаемым образом только потому, что возвращаемое значение GetStringSubset() и запрос LINQ внутри этого метода были строго типизированными. Если применить ключевое слово var для определения переменной subset, то возвращать значение будет разрешено, только если метод по-прежнему прототипирован с возвращаемым типом IEnumerable<string> (и если неявно типизированная локальная переменная на самом деле совместима с указанным возвращаемым типом).
Поскольку оперировать с типом IEnumerable<T> несколько неудобно, можно задействовать немедленное выполнение. Скажем, вместо возвращения IEnumerable<string> можно было бы возвратить просто string[] при условии трансформации последовательности в строго типизированный массив. Именно такое действие выполняет новый метод класса Program:
static string[] GetStringSubsetAsArray()
{
string[] colors = {"Light Red", "Green",
"Yellow", "Dark Red", "Red", "Purple"};
var theRedColors = from c in colors where c.Contains("Red") select c;
// Отобразить результаты в массив.
return theRedColors.ToArray();
}
В таком случае вызывающий код совершенно не знает, что полученный им результат поступил от запроса LINQ, и просто работает с массивом строк вполне ожидаемым образом. Вот пример:
foreach (string item in GetStringSubsetAsArray())
{
Console.WriteLine(item);
}
Немедленное выполнение также важно при попытке возвратить вызывающему коду результаты проецирования LINQ. Мы исследуем эту тему чуть позже в главе. А сейчас давайте посмотрим, как применять запросы LINQ к обобщенным и необобщенным объектам коллекций.
- Понимание SQL - Мартин Грубер - Базы данных