Last active
May 2, 2023 11:21
-
-
Save noseratio/93058387f0ce8c401c2e8ae30fd5483c to your computer and use it in GitHub Desktop.
Re-implement an `IEnumerable` method without `yield`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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