Created
May 2, 2015 20:18
-
-
Save jnm2/21efb048c94c23837598 to your computer and use it in GitHub Desktop.
Gives foreach recursive abilities without recursive calls
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
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
public sealed class StackEnumerator<T> : IDisposable | |
{ | |
private readonly Stack<IEnumerator<T>> stack = new Stack<IEnumerator<T>>(); | |
private IEnumerator<T> current; | |
public bool MoveNext() | |
{ | |
while (!current.MoveNext()) | |
{ | |
current.Dispose(); | |
if (stack.Count == 0) return false; | |
current = stack.Pop(); | |
} | |
return true; | |
} | |
public T Current | |
{ | |
get { return current.Current; } | |
} | |
public void Recurse(IEnumerator<T> newCurrent) | |
{ | |
stack.Push(current); | |
current = newCurrent; | |
} | |
public void Recurse(IEnumerable<T> newCurrent) | |
{ | |
Recurse(newCurrent.GetEnumerator()); | |
} | |
public StackEnumerator(IEnumerator<T> initial) | |
{ | |
current = initial; | |
} | |
public StackEnumerator(IEnumerable<T> initial) : this(initial.GetEnumerator()) | |
{ | |
} | |
public StackEnumerator(T initial) : this(new[] { initial }) | |
{ | |
} | |
// Foreach support | |
[EditorBrowsable(EditorBrowsableState.Never)] | |
public StackEnumerator<T> GetEnumerator() | |
{ | |
return this; | |
} | |
public void Dispose() | |
{ | |
current.Dispose(); | |
foreach (var item in stack) | |
item.Dispose(); | |
stack.Clear(); | |
} | |
} | |
public sealed class StackEnumerator<TContext, T> : IDisposable | |
{ | |
public struct ContextCurrent | |
{ | |
private readonly TContext context; | |
public TContext Context { get { return context; } } | |
private readonly T current; | |
public T Current { get { return current; } } | |
public ContextCurrent(TContext context, T current) | |
{ | |
this.context = context; | |
this.current = current; | |
} | |
} | |
private readonly Stack<Tuple<TContext, IEnumerator<T>>> stack = new Stack<Tuple<TContext, IEnumerator<T>>>(); | |
private Tuple<TContext, IEnumerator<T>> current; | |
public bool MoveNext() | |
{ | |
while (!current.Item2.MoveNext()) | |
{ | |
current.Item2.Dispose(); | |
if (stack.Count == 0) return false; | |
current = stack.Pop(); | |
} | |
return true; | |
} | |
public ContextCurrent Current | |
{ | |
get { return new ContextCurrent(current.Item1, current.Item2.Current); } | |
} | |
public void Recurse(TContext newContext, IEnumerator<T> newCurrent) | |
{ | |
stack.Push(current); | |
current = Tuple.Create(newContext, newCurrent); | |
} | |
public void Recurse(TContext newContext, IEnumerable<T> newCurrent) | |
{ | |
Recurse(newContext, newCurrent.GetEnumerator()); | |
} | |
public void Recurse(TContext newContext, T newCurrent) | |
{ | |
Recurse(newContext, new[] { newCurrent }); | |
} | |
public StackEnumerator(TContext initialContext, IEnumerator<T> initial) | |
{ | |
current = Tuple.Create(initialContext, initial); | |
} | |
public StackEnumerator(TContext initialContext, IEnumerable<T> initial) : this(initialContext, initial.GetEnumerator()) | |
{ | |
} | |
public StackEnumerator(TContext initialContext, T initial) : this(initialContext, new[] { initial }) | |
{ | |
} | |
// Foreach support | |
[EditorBrowsable(EditorBrowsableState.Never)] | |
public StackEnumerator<TContext, T> GetEnumerator() | |
{ | |
return this; | |
} | |
public void Dispose() | |
{ | |
current.Item2.Dispose(); | |
foreach (var item in stack) | |
item.Item2.Dispose(); | |
stack.Clear(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment