函数返回具有分配的所有子代的新列表VS函数返回没有分配的该子代的列表

时间:2019-09-04 14:13:04

标签: c#

我正在尝试一种方法来遍历对象的所有子代(包括子代子代)而不创建垃圾分配。

我之前拥有的函数是一个递归函数,它返回了一个列表。

现在我有两个函数,一个函数返回一个计数,另一个函数使孩子处于某个索引处。

我觉得可能有更好的方法遍历对象的所有子对象

这里是比较递归列表和递归计数+ getAt(index)的示例代码


public class MyClassWithChildren
{
    private MyClassWithChildren[] m_Children;

    //With allocation
    public IReadOnlyList<MyClassWithChildren> GetAllChildren(bool includeThis = false)
    {
        var allChildren = new List<MyClassWithChildren>();
        if (includeThis) {
            allChildren.Add(this);
        }

        if (m_Children != null) {
            for (int i = 0; i < m_Children.Length; i++) {
                allChildren.AddRange(m_Children[i].GetAllChildren(true));
            }
        }
        return allChildren;
    }


    //Without allocation combination of count and getAt(index) 


    public int GetAllChildrenCount(bool includeThis = false)
    {
        var count = 0;
        if (includeThis) { count++; }

        for (int i = 0; i < m_Children.Length; i++) {
            count += 1 + m_Children[i].GetAllChildrenCount();
        }

        return count;
    }

    public MyClassWithChildren GetAllChildrenAt(int index, bool includeThis = false)
    {

        if (includeThis) {
            if (index == 0) { return this;}
            index--;
        }

        for (int i = 0; i < m_Children.Length; i++) {
            if (index == 0) { return m_Children[i]; }

            index--;

            var newIndex = index - m_Children[i].GetAllChildrenCount(false);
            if (newIndex < 0) { return m_Children[i].GetAllChildrenAt(index); }

            index = newIndex;
        }

        return null;
    }
}

有人知道更好的方法吗? 一个简单的用例是搜索某个对象是否是另一个对象的子对象。 另一个办法是找到所有具有特定属性值的孩子。

谢谢您的时间

1 个答案:

答案 0 :(得分:1)

也许这就是您想要的:

adapter.notifyDataSetChanged();

这将在外部循环处理完返回值并请求下一个值之后,评估返回值的子级。这意味着所有孩子都是懒惰的。如果您的外部循环将在第一个元素之后停止,则仅将此元素排入结果队列。 public IEnumerable<MyClassWithChildren> GetAllChildren() { var items = new Queue<MyClassWithChildren>(); items.Enqueue(this); while (items.TryDequeue(out var result)) { yield return result; for (var i = 0; i < result.m_children.Length; ++i) // use for instead of foreach to avoid enumerator creation { items.Enqueue(result.m_children[i]); } } } 中的枚举数没有开销,因为此代码使用m_children循环而不是for循环。

如果您需要所有元素的数量-只需使用linq:foreach