IEnumerable<T>
объекты имеют отложенное выполнение, что означает, что они выполняются, когда к ним обращаются для итерации.Когда мы начинаем итерацию или материализацию объекта этого объекта в List<T>
или Array
, тогда он фактически вызывается.
Если вы добавите вызов ToList()
в свой метод ForEach
, вы увидите ожидаемый результат:
After(ForEach(Sample(10), v => item = v).ToList(), () => Console.WriteLine(item));
Как вы видели, вы материализовали результирующий метод ForEach()
IEnumerable
, он также вызовет Sample()
и выполнит.
Вы можете изменить ваши методы, как показано ниже, чтобы увидетькогда на самом деле метод был вызван:
static IEnumerable<int> Sample(int count)
{
Console.WriteLine("Sample Invoked");
for (int i = 0; i < count; i++)
yield return i;
}
static IEnumerable<int> ForEach(IEnumerable<int> items, Action<int> action)
{
Console.WriteLine("ForEach Invoked:");
foreach (int item in items)
{
action(item);
yield return item;
}
}
, а затем вызвать его следующим образом:
int item = -1;
After(ForEach(Sample(10), v => item = v), () => Console.WriteLine(item));
Console.WriteLine(item);
After(ForEach(Sample(10), v => item = v).ToList(), () =>
Console.WriteLine(item));
Console.WriteLine(item);
и получится:
-1
-1
Активировано ForEach:
Вызван образец
9
9
См. Fiddle DEMO чтобы наблюдать за ним в действии.