Ability to reset IEnumerator generated using yield (C#)

c#

Solution

There is no built-in support, but you can define your own implementation of `IEnumerator` that delegates all method calls to the enumerator generated by C# and only lets you define your own behavior for the `Reset` method.

The simplest version of the class would look like this:

class ResetableEnumerator<T> : IEnumerator<T>
{
  public IEnumerator<T> Enumerator { get; set; }
  public Func<IEnumerator<T>> ResetFunc { get; set; }

  public T Current { get { return Enumerator.Current; } }
  public void  Dispose() { Enumerator.Dispose(); }
  object IEnumerator.Current { get { return Current; } }
  public bool  MoveNext() { return Enumerator.MoveNext(); }
  public void  Reset() { Enumerator = ResetFunc(); }
}

In this case, the `ResetFunc` that you specify returns a new `IEnumerator<T>`, so your provided implementation of `ResetFunc` can do some cleanup or whatever you need to do when resetting and then return a new enumerator.

IEnumerator<int> Foo() { /* using yield return */ }
IEnumerator<int> PublicFoo() {
  return new ResetableEnumerator<int> { 
    Enumerator = Foo(),
    ResetFunc = () => { 
      Cleanup();
      return Foo(); } };
}

You'll need to store all the originally local variables of the `Foo` method as fields of the class, so that you can access them in `Cleanup` (Note that the rest of the `Foo` body will never be executed after calling `Reset`), but that's still easier than writing a handwritten iterator!

Problem

If I use yield instead of manually creating an IEnumerator, is it possible to implement IEnumerator.Reset?

Original source