You're alongMost of the right lines in identifying that IEnumerable andtime, a simple IEnumeratorforeach are very powerful concepts that can often help you in situations like this. However, having to directly deal withiteration over an IEnumeratorIEnumerable<T> is usually annoyingwhat you want for iterative logic. But in some cases- that's why things like IEnumerable, foreach and yieldtree-related algorithms are therean area this often occurs- a different data structure will serve you better. In this case, considerI'd suggest storing your children in a wrapper classStack. Then your loop can look like:
class OneTimeEnumerable<T> : IEnumerable<T> while(subTasks.Any())
{
private IEnumerator<T> _inner;
var next = subtasks.Pop();
public OneTimeEnumerable Status subtaskStatus = next.Tick(IEnumerable<T> sourceai );
switch( subtaskStatus ){
_inner = source case Status.GetEnumerator();SUCCESS:
}
public IEnumerator<T> GetEnumerator() break; //Break switch and move on to next subtask tick..
{ case Status.FAILURE:
return _inner;
subtaskStatus; //Back out early }when any subtask fails..
case Status.RUNNING:
IEnumerator IEnumerable subtasks.GetEnumeratorPush(next)
; //Push it back {onto the stack so it'll be first in line next time
return GetEnumerator();subtaskStatus; //Back out early and resume/retick running task time!
}
}
All this does is give you an IEnumerable<T> which always returns the same enumerator back (with its Current in the same position), rather thanAs a new one each time. Then you can store this, and foreach over it as usualside note, rather than havingif you do have cause to deal with too-low-level things like MoveNexts.
Note, by the way, that I'm using the genericuse IEnumerator and IEnumerable. You, you should pretty much always do thisuse the generic versions, in the same way that you'd always choose to use a List<Task> to hold tasks rather than a List<object>