When you want to recursively enumerate a hierarchical object, selecting some elements based on some criteria, there are numerous examples of techniques like \"flattening\" a
This code should do the trick
public static class Extensions
{
public static IEnumerable GetRecursively(this IEnumerable collection,
Func selector)
{
foreach (var item in collection.OfType())
{
yield return item;
IEnumerable children = selector(item).GetRecursively(selector);
foreach (var child in children)
{
yield return child;
}
}
}
}
Here's an example of how to use it
TreeView view = new TreeView();
// ...
IEnumerable nodes = view.Nodes.
.GetRecursively(item => item.Nodes);
Update: In response to Eric Lippert's post.
Here's a much improved version using the technique discussed in All About Iterators.
public static class Extensions
{
public static IEnumerable GetItems(this IEnumerable collection,
Func selector)
{
Stack> stack = new Stack>();
stack.Push(collection.OfType());
while (stack.Count > 0)
{
IEnumerable items = stack.Pop();
foreach (var item in items)
{
yield return item;
IEnumerable children = selector(item).OfType();
stack.Push(children);
}
}
}
}
I did a simple performance test using the following benchmarking technique. The results speak for themselves. The depth of the tree has only marginal impact on the performance of the second solution; whereas the performance decreases rapidly for the first solution, eventually leadning to a StackOverflowException
when the depth of the tree becomes too great.