Расширение GroupBy
на самом деле совсем не ленивое (или, точнее, вовсе не отсроченное ), что можно легко продемонстрировать с помощью следующей тестовой программы:
void Main()
{
var source = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }.AsParallel();
var groupEven = GetEvenNumbersUsingGroupBy(source);
// foreach (int num in groupEven) { }
}
IEnumerable<int> GetEvenNumbersUsingGroupBy(IEnumerable<int> source)
{
Console.WriteLine("Method called: GetEvenNumbersUsingGroupBy");
var grouped = source.GroupBy(i => i % 2);
return grouped.Where(g => g.Key == 0).Single();
}
Эта программа выводит следующее:
Вызванный метод: GetEvenNumbersUsingGroupBy
Это означает, что даже если мы на самом деле никогда не повторяем результат метода GetEvenNumbersUsingGroupBy
,он по-прежнему выполняется.
Это отличается от обычного отложенного перечисления с использованием оператора yield
, например:
void Main()
{
var yieldEven = GetEvenNumbersUsingYield(source);
foreach (int num in yieldEven) { }
foreach (int num in yieldEven) { }
}
IEnumerable<int> GetEvenNumbersUsingYield(IEnumerable<int> source)
{
Console.WriteLine("Method called: GetEvenNumbersUsingYield");
foreach (int i in source)
if ((i % 2) == 0)
yield return i;
}
Это печатает следующее:
Метод называется: GetEvenNumbersUsingYield
Метод называется: GetEvenNumbersUsingYield
Другими словами, каждый раз, когда вы повторяете результаты, они переоцениваются, что является типичной характеристикой отложенной оценки (каквместо прямой ленивой загрузки, которая кэширует результат после первой оценки).
Обратите внимание, что это то же самое, используете ли вы AsParallel
или нет;это характеристика расширения GroupBy
(которое по определению должно создавать хэш-таблицу или другой вид поиска для хранения отдельных групп) и полностью независимое от параллелизма.
Легко понять, почему этоэто тот случай, если вы думаете, как бы вы реализовали функцию отложенной группировки;для того, чтобы выполнить итерацию всех элементов одной группы, вам нужно будет выполнить итерацию всей последовательности, чтобы быть уверенным, что вы действительно охватили все элементы этой группы.Таким образом, хотя технически может быть возможно отложить эту одноразовую итерацию всей последовательности, в большинстве случаев это, вероятно, не стоит, так как он будет иметь те же характеристики памяти и процессора, что и узагруженная версия.