递归和收益 return

Recursion and Yield return

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

return 它作为 IEnumerable 我是 运行 foreachHandleChildItems 方法的项目列表上循环 yield return.

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

有没有办法在调用递归方法本身的同时处理这个问题?

private IEnumerable<object> HandleChildItems()
{ 
    var childItemslst = new List<Item>(); 
    childItemslst = GetChildItems(xmlnode);

    foreach (var item in childItemslst)
    {
        yield return item ;
    }
}

private List<Item> GetchildItems(XMLnodeList nodeList)
{
    List<Item> lstItem = new List<Item>();
    // 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);
        }
        else
        {
            item = new Item
                   {
                       Code = "123",
                       Itemtext = "xyz"                            
                   };          
        }
        lstItem.add(item);
    }
}

List<> 已经是 IEnumerable。您不必转换它。

引用 documentation:

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

并且可以通过 List.AddRange()

添加子列表

我能想到至少两个比你现在做的更好的选择:

  1. 通过将对象传递给递归方法,以递归方式构建单个 List<T> 对象。
  2. 根本不要构建 List<T> 对象;相反,只是递归地计算迭代器。

#1 的示例(除了原始代码中最明显的 bugs/syntax 错误外,我没有尝试清理任何错误):

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> 本身。但它确实需要将整个列表一次存储在内存中。

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