如何从具有n个子/子子的CustomObject获取所有子对象,依此类推

时间:2011-12-12 14:41:48

标签: c# .net list children

我有一个带有n个孩子的CustomObject。这些子项是CustomObjects列表。像这样:

public class CustomObject
{
    public List<CustomObject> Children = new List<CustomObject>();
}

我正在寻找的是从单个CustomObject实例获得所有n个孩子及其子女和子女等的最高效的方法。有没有比循环遍历所有veg更好的方法,直到我到达结尾(null)?

(C#,.NET 3.5)

为了更清楚,我将做一个示例结构:

//root object
CustomObject.Children ->
    CustomObject.Children ->
         CustomObject
         CustomObject
    CustomObject.Children ->
         CustomObject.Children ->
             CustomObject
         CustomObject
    CustomObject

在这种情况下,我需要在根对象下面获取所有自定义对象。

6 个答案:

答案 0 :(得分:7)

不,你只需循环一切。您可以使用递归方法:

public void GetItems(List<CustomObject> list) {
  list.Add(this);
  foreach (CustomObject child in Childs) {
    child.GetItems(list);
  }
}

用法:

List<CustomObject> items = new List<CustomObject>();
someCustomObject.GetItems(items);

注意:复数形式的孩子孩子

答案 1 :(得分:4)

我使用这种扩展方法:

public static IEnumerable<T> Flatten<T>(this IEnumerable<T> hierarchy, Func<T, IEnumerable<T>> lambda)
    {
        var result = new List<T>();

        foreach (var item in hierarchy)
        {
            result.AddRange(Flatten(lambda(item), lambda));
            if (!result.Contains(item))
                result.Add(item);
        }

        return result;
    }
你会这样称呼它:

MyObject.Childs.Flatten(c => c.Childs);

这是一个相当丑陋的覆盖,如果需要,可以添加根对象:

public static IEnumerable<T> Flatten<T>(this T @this, Func<T, IEnumerable<T>> lambda)
{
    return new[] { @this }.Flatten(lambda);
}

答案 2 :(得分:2)

可能不是,但它完全取决于你是如何做到的。您可以递归使用yield

public IEnumerable<CustomObject> AndChildren()
{
  yield return this;
  foreach(var child in Childs)
  {
    foreach(var nested in child.AndChildren())
    {
      yield return nested;
    }
  }
}

它有明显的好处,它是晚期的,因此你的内存消耗要好得多。缺点是它对树内任何节点进行的任何修改都非常脆弱(如果修改了任何列表,foreach迭代器将在下一个引发异常。)

要解决这个问题,您可以使用Linq .ToArray()方法急切加载结果。

所以现在,如果你想遍历整个树,你只需:

foreach(var obj in the_root_object.AndChildren())
{

}

假设the_root_objectCustomObject的一个具有各种“静脉”的实例,正如您所说的那样。

如果对对象应该相对于子女出现的顺序有特定要求,则必须稍微重写。

答案 3 :(得分:2)

您必须遍历每个Childs集合。你可以考虑这样的事情:

public class CustomObject
{
    public List<CustomObject> Childs = new List<CustomObject>();

    protected IEnumerable<CustomObject> GetDecendants()
    {
        foreach (var child in Childs)
        {
            yield return child;
            foreach (var grandchild in child.GetDecendants())
            {
                yield return grandchild;
            }
        }
    }
}

答案 4 :(得分:1)

我只是使用循环和递归,不能简单得多!

private List<CustomObject> GetChildObjects(CustomObject)
{
   List<CustomObject> retList = CustomObject.Childs;

   foreach(CustomerObject obj in retList)
   {
      retList.AddRange(GetChildObjects(obj));
   }

   return retList;
}

答案 5 :(得分:0)

如果你对维护这些对象的层次结构不感兴趣,但只是在获得所有这些对象之后(如果你的话,我无法从你的帖子中找到),你也可以考虑使用Reflection获取所有对象类型CustomObject:

List<CustomObject> Objects = new List<CustomObject>();

Assembly asm = Assembly.LoadFrom(assemblyPath);
Type[] types = asm.GetTypes();

foreach (var t in types)
{
    if (t.IsClass && t.IsSubclassOf(typeof(CustomObject)))
    {
        var instance = (CustomObject) Activator.CreateObject(t);

        if (!Objects.Contains(instance))
            Objects.Add(instance);
    }
}

特别是在大型应用程序中,运行大量循环会对性能产生巨大影响,使用Reflection通常是一个不错的选择。