using System.Collections.Generic;
using System.Diagnostics;
public static class Program
public static void Main()
IEnumerable<int> source = Iterator();
Enumerate("Source.Take(5)", source.Take(5));
Enumerate("Source", source);
Enumerate("Source.TakeLast(5)", source.TakeLast(5));
Console.Write($"Source.Sum(): "); Console.WriteLine(source.Sum());
var memoised = source.MemoiseNotSynchronized();
Enumerate("Memoised.Take(5)", memoised.Take(5));
Enumerate("Memoised", memoised);
Enumerate("Memoised.TakeLast(5)", memoised.TakeLast(5));
Console.Write($"Memoised.Sum(): "); Console.WriteLine(memoised.Sum());
static IEnumerable<int> Iterator()
Console.Write("Starting! ");
try { foreach (var i in Enumerable.Range(1, 10)) yield return i; }
finally { Console.Write("Finished! "); }
static void Enumerate(string title, IEnumerable<int> sequence)
Console.Write($"{title}: ");
foreach (var i in sequence) Console.Write($"{i}, ");
public static IEnumerable<T> MemoiseNotSynchronized<T>(this IEnumerable<T> source)
IEnumerator<T> enumerator = null;
IEnumerable<T> Implementation()
if (buffer != null && enumerator == null)
foreach (var item in buffer) yield return item;
enumerator ??= source.GetEnumerator();
for (int i = 0; ; i = checked(i + 1))
else if (enumerator.MoveNext())
Debug.Assert(buffer.Count == i);
var current = enumerator.Current;
enumerator.Dispose(); enumerator = null;