Enumerating Collections that are not inherently IEnumerable?

后端 未结 5 1603
予麋鹿
予麋鹿 2020-11-29 03:45

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

5条回答
  •  温柔的废话
    2020-11-29 03:58

    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.

    benchmarking

提交回复
热议问题