递归和收益率回报

时间:2015-01-28 06:57:45

标签: c# foreach

我有一个方法HandleChildItems,它返回IEnumerable<object>。此方法又调用方法GetChildItems。在GetChildItems方法中,我进行递归调用以将项添加到列表中,然后GetChildItems方法将列表返回到HandleChildItems方法。

要将其作为IEnumerable返回,我在使用foreach的{​​{1}}方法中的项目列表上运行HandleChildItems循环。

但是这似乎花费了更多的时间,因为我的xml文件有超过10万个条目。

有没有办法在调用递归方法时能够处理这个问题?

yield return

2 个答案:

答案 0 :(得分:2)

列表&lt;&gt;已经是IEnumerable了。你不必转换它。

引用documentation

public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable

添加子列表可以通过List.AddRange()

完成

答案 1 :(得分:0)

我至少可以想到两种比你现在所做的更好的选择:

  1. 通过将对象传递给递归方法,以递归方式构建单个List<T>对象。
  2. 根本不构建List<T>个对象;相反,只是递归地评估迭代器。
  3. #1的示例(我没有费心去尝试清除原始代码中最明显的错误/语法错误):

    private IEnumerable<object> HandleChildItems()
    { 
        var itemsList = new List<Item>(); 
    
        GetChildItems(xmlnode, itemsList);
    
        // IEnumerable<T> is covariant
        return itemsList;    
    }
    
    private void GetChildItems(XMLnodeList nodeList, List<Item> itemsList)
    {
        // Here I recursively call the method to add the items to list
        foreach (xmlnode xn in nodeList)
        {
            if (xn.childnodes.count > 0)
            {
                GetChildItems(xn.childnodes, itemsList);
            }
            else
            {
                itemsList.Add(new Item { Code = "123", Itemtext = "xyz" });
            }
        }
    }
    

    #2的例子:

    private IEnumerable<object> HandleChildItems()
    { 
        foreach (Item item in GetChildItems(xmlnode))
        {
            yield return item;
        }
    }
    
    private IEnumerable<Item> GetChildItems(XMLnodeList nodeList)
    {
        // Here I recursively call the method to add the items to list
        foreach (xmlnode xn in nodeList)
        {
            if (xn.childnodes.count > 0)
            {
                foreach (Item item in GetChildItems(xn.childnodes))
                {
                    yield return item;
                }
            }
            else
            {
                yield return new Item { Code = "123", Itemtext = "xyz" };
            }
        }
    }
    

    示例#1的优点是您只创建一个中间对象List<Item>本身。但它确实需要将整个列表一次存储在内存中。

    Example#2创建了一个潜在的大量迭代器方法对象,每个递归级别对应一个。但是这个数字可能比您必须创建的Item个对象的总数要小得多,而且您确实可以避免必须同时将所有这些Item个对象存储在内存中。