我有一个带有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
在这种情况下,我需要在根对象下面获取所有自定义对象。
答案 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_object
是CustomObject
的一个具有各种“静脉”的实例,正如您所说的那样。
如果对对象应该相对于子女出现的顺序有特定要求,则必须稍微重写。
答案 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通常是一个不错的选择。