如何返回所有子对象 - 我无法让SelectMany工作

时间:2012-10-19 09:09:24

标签: linq

我有一个班级

    public class Foo
    {
       public IList<Foo> Items { get; set; }
    }

    public class FooList
    {
       public IList<Foo> Items { get; set; }
    }

我希望能够将所有Foo对象放在一个列表中,而不是层次结构中。

我试过了

    IEnumerable<Foo> result = Items.SelectMany(f =>  f.Items);

但这只是获取该特定对象中的项目 - 它不会获取所有子对象中的所有项目。

我也试过

    IEnumerable<Foo> result = Items.SelectMany(t => t)

但我收到错误:

  

无法从用法推断出方法'System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable,System.Func&gt;)'的类型参数。尝试明确指定类型参数。

2 个答案:

答案 0 :(得分:0)

假设您有一个名为FooList的{​​{1}}实例:

您需要在fooList类中定义这样的方法:

FooList

然后致电

public IEnumerable<Foo> GetRecursiveFoos()
{
    return Items.Concat(Items.SelectMany(x => x.Items));
}

答案 1 :(得分:0)

将一个类似LINIT的“flatten-this-tree”函数拼凑起来相当容易,你可以在更一般的情况下使用它:

public static IEnumerable<T> Flatten<T>(
    this IEnumerable<T> source,
    Func<T, IEnumerable<T>> childSelector)
{
    HashSet<T> added = new HashSet<T>();
    Queue<T> queue = new Queue<T>();
    foreach(T t in source)
        if (added.Add(t))
            queue.Enqueue(t);
    while (queue.Count > 0)
    {
        T current = queue.Dequeue();
        yield return current;
        if (current != null)
        {
            IEnumerable<T> children = childSelector(current);
            if (children != null)
                foreach(T t in childSelector(current))
                    if (added.Add(t))
                        queue.Enqueue(t);
        }
    }
}

然后,如果您有FooList,则可以使用

var allFoos = myFooList.Items.Flatten(foo => foo.Items);

获取列表中的所有Foo以及他们所有的孩子以及所有他们的子女和...