If I use yield instead of manually creating an IEnumerator, is it possible to implement IEnumerator.Reset?
My solution to this problem is to use a Wrapper class that can wrap any yielding function and reset:
public class Resettable : IEnumerator
{
private IEnumerator inner;
private Func func;
public Resettable(Func func)
{
this.func = func;
inner = func.Invoke();
}
public bool MoveNext()
{
return inner.MoveNext();
}
public object Current { get { return inner.Current; } }
public void Reset()
{
inner = func.Invoke();
}
public static Resettable Make(Func func)
{
return new Resettable(func);
}
public static Resettable Make(Func func, T1 a1)
{
Func capture = () => { return func.Invoke(a1); };
return new Resettable(capture);
}
public static Resettable Make(Func func, T1 a1, T2 a2)
{
Func capture = () => { return func.Invoke(a1, a2); };
return new Resettable(capture);
}
public static Resettable Make(Func func, T1 a1, T2 a2, T3 a3)
{
Func capture = () => { return func.Invoke(a1, a2, a3); };
return new Resettable(capture);
}
// add more of these to support more arguments
}
then, instead of calling your yielding method directly, you call Resettable.Make(YourMethod, ..arguments..);
so, here's an example usage:
public class Program
{
static IEnumerator YieldTest(int start)
{
yield return start;
yield return start + 1;
yield return start + 2;
}
public static void Main()
{
// IEnumerator en = YieldTest(5);
IEnumerator en = Resettable.Make(YieldTest, 5);
while(en.MoveNext())
{
Console.WriteLine("value: "+en.Current.ToString());
}
Console.WriteLine("Reset");
en.Reset();
while(en.MoveNext())
{
Console.WriteLine("value: "+en.Current.ToString());
}
}
}
Output:
value: 5
value: 6
value: 7
Reset
value: 5
value: 6
value: 7