ОКОНЧАТЕЛЬНОЕ ИЗОБРАЖЕНИЕ:
Я выбрал Тимоти, но если вы хотите, чтобы cuter-реализация, использующая оператор С# yield, проверяет ответ Eamon: qaru.site/info/309876/...
По умолчанию LINQ запросы лениво передаются.
ToArray
/ToList
дают полную буферизацию, но сначала они нетерпеливы, а во-вторых, для завершения бесконечной последовательности может потребоваться довольно много времени.
Есть ли способ иметь комбинацию обоих типов поведения: потокового и буферизации на лету, поскольку они сгенерированы, так что следующий запрос не будет запускаться генерация элементов, которые уже были запрошены.
Вот пример использования:
static IEnumerable<int> Numbers
{
get
{
int i = -1;
while (true)
{
Console.WriteLine("Generating {0}.", i + 1);
yield return ++i;
}
}
}
static void Main(string[] args)
{
IEnumerable<int> evenNumbers = Numbers.Where(i => i % 2 == 0);
foreach (int n in evenNumbers)
{
Console.WriteLine("Reading {0}.", n);
if (n == 10) break;
}
Console.WriteLine("==========");
foreach (int n in evenNumbers)
{
Console.WriteLine("Reading {0}.", n);
if (n == 10) break;
}
}
Вот результат:
Generating 0.
Reading 0.
Generating 1.
Generating 2.
Reading 2.
Generating 3.
Generating 4.
Reading 4.
Generating 5.
Generating 6.
Reading 6.
Generating 7.
Generating 8.
Reading 8.
Generating 9.
Generating 10.
Reading 10.
==========
Generating 0.
Reading 0.
Generating 1.
Generating 2.
Reading 2.
Generating 3.
Generating 4.
Reading 4.
Generating 5.
Generating 6.
Reading 6.
Generating 7.
Generating 8.
Reading 8.
Generating 9.
Generating 10.
Reading 10.
Код генерации запускается 22 раза.
Я бы хотел, чтобы он запускался 11 раз, при первом повторном перечислении.
Тогда вторая итерация выиграла бы от уже сгенерированных значений.
Это будет что-то вроде:
IEnumerable<int> evenNumbers = Numbers.Where(i => i % 2 == 0).Buffer();
Для тех, кто знаком с Rx, это похоже на a ReplaySubject
.