使用Linq遍历树状结构

时间:2016-03-30 12:28:56

标签: c# linq c#-4.0 extension-methods

我有一个像这样的结构的对象:

    public class CustomObject
    {
        public int CustomProperty{get;set;}
        public string CustomStringProperty{get;set;}
        public List<CustomObject> CustomObjects{get;set;}
    }

我知道有很多方法我可以根据CustomProperty上的某些条件提取任何对象,其父对象或获取对象。

我想编写一些扩展方法或linq,以便客户可以访问每个对象及其属性。

目前客户有列表 - &gt; List<CustomObject>();

例如。 ClientMethod(List<CustomObject> customObjs);

1 个答案:

答案 0 :(得分:2)

假设您希望能够遍历列表中的项目及其所有子项。

像往常一样,我建议你从How to flatten tree via LINQ?获得高效的通用树预订遍历方法:

public static partial class TreeHelper
{
    public static IEnumerable<T> Expand<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
    {
        var stack = new Stack<IEnumerator<T>>();
        var e = source.GetEnumerator();
        try
        {
            while (true)
            {
                while (e.MoveNext())
                {
                    var item = e.Current;
                    yield return item;
                    var elements = elementSelector(item);
                    if (elements == null) continue;
                    stack.Push(e);
                    e = elements.GetEnumerator();
                }
                if (stack.Count == 0) break;
                e.Dispose();
                e = stack.Pop();
            }
        }
        finally
        {
            e.Dispose();
            while (stack.Count != 0) stack.Pop().Dispose();
        }
    }
}

并根据您的需要使用它(如果您不喜欢,可以使用其他名称):

partial class TreeHelper
{
    public static IEnumerable<CustomObject> Expand(this IEnumerable<CustomObject> source)
    {
        return source.Expand(item => item.CustomObjects != null && item.CustomObjects.Count > 0 ? item.CustomObjects : null);
    }
}

然后你可以简单地使用:

void ClientMethod(List<CustomObject> customObjs)
{
    foreach (var item in customObjs.Expand())
    {
        // do something
    }
}

或LINQ查询,如customObjs.Expand().Where(...)等。