Skip to content

Instantly share code, notes, and snippets.

@noseratio
Last active May 2, 2023 11:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noseratio/93058387f0ce8c401c2e8ae30fd5483c to your computer and use it in GitHub Desktop.
Save noseratio/93058387f0ce8c401c2e8ae30fd5483c to your computer and use it in GitHub Desktop.
Re-implement an `IEnumerable` method without `yield`
// https://twitter.com/noseratio/status/1491189525061980160
using System.Collections;
using System.Diagnostics.CodeAnalysis;
foreach (var item in Generate())
{
Console.WriteLine(item);
}
foreach (var item in GenerateWithoutYield())
{
Console.WriteLine(item);
}
static IEnumerable<int> Generate()
{
var sum = 0;
for (int i = 0; i < 10; i++)
{
yield return sum += i;
}
}
static IEnumerable<int> GenerateWithoutYield()
{
return new Generator<int>(() =>
{
var sum = 0;
var i = 0;
return () =>
{
if (i < 10)
{
return (sum += i++, true);
}
return (default, false);
};
});
}
public partial class Generator<T> : IEnumerable<T>
{
public delegate (T item, bool itemProvided) OnNext();
readonly Func<OnNext> _onNextFactory;
public Generator(Func<OnNext> onNextFactory) => _onNextFactory = onNextFactory;
public IEnumerator<T> GetEnumerator() => new Enumerator(_onNextFactory());
IEnumerator IEnumerable.GetEnumerator() =>
throw new NotImplementedException();
}
public partial class Generator<T>
{
class Enumerator : IEnumerator<T>
{
readonly OnNext _onNext;
[AllowNull]
T _item = default;
bool _itemProvided;
public T Current => _itemProvided ? _item : throw new InvalidOperationException();
object IEnumerator.Current => throw new NotImplementedException();
public Enumerator(OnNext onNext) => _onNext = onNext;
public void Dispose()
{
}
public bool MoveNext()
{
(_item, _itemProvided) = _onNext();
return _itemProvided;
}
public void Reset() => throw new NotImplementedException();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment