如何使用LINQ返回对象的祖先?

时间:2010-05-13 05:09:08

标签: c# linq

我有一个看起来像这样的区类:

public class District
{
    public int Id { get; set; }
    public string Name { get; set; }
    public District Parent { get; set; }
    public IEnumerable<District> Ancestors { get { /* what goes here? */ } }
}

我希望能够得到每个区的祖先名单。因此,如果区“1.1.1”是区域“1.1”的子区域,这是区域“1”的子区域,则获得区域“1.1.1”上的祖先将返回包含名称为“1.1”的区域对象的列表。 “和”1“。

这是否涉及收益率报表(我从未完全理解)? 可以一行完成吗?

3 个答案:

答案 0 :(得分:10)

如果线条足够长,一切都可以在一行中完成:)

在这种情况下,它可能最简单不在一行中完成:

public IEnumerable<District> Ancestors
{
    get
    {
        District parent = Parent;
        while (parent != null)
        {
            yield return parent;
            parent = parent.Parent;
        }
    }
}

如果你想更好地理解yield return,只需要一个简短的插件 - 深度C#第一版的第6章仍然可以免费获得,而这一切都是关于C#2中的迭代器。从{{抓住它3}}

答案 1 :(得分:1)

你可能想要考虑这个替代方案......它不是“纯粹的”,而是一种轻松查询此类事物的大规模有效方式。 (无论是否使用sql)

SQL select descendants of a row

请参阅“已接受”答案

我唯一要添加的是标签之间的分隔符

哦,然后使用linq查询

ancestors = Districts.Where( d => 
       d.Pedigree.Contains(Id) && 
       d.Pedigree.Length < Pedigree)
       .ToList();

如果您使用ORM,那么这将导致单个查询,而不是尝试迭代树时的许多查询

实际上在这个单亲的情况下,它更容易,因为你的血统将包含你的血统,但如果你有一个分支祖先..... :)

答案 2 :(得分:1)

这是一个通用的扩展方法,用于根据接受的答案获取对象的祖先集合:

static public IEnumerable<T> GetAncestors<T>(this T source, Func<T, T> parentOf)
{
    var Parent = parentOf(source);
    while (Parent != null)
    {
        yield return Parent;
        Parent = parentOf(Parent);
    }
}

所以我可以将它用于我的应用程序中的所有层次结构:

public IEnumerable<District> Ancestors
{
    get
    {
        return this.GetAncestors(d => d.Parent);
    }
}

或展开给定TreeView节点的所有父节点......

Node.GetAncestors(node => node.Parent).ToList().ForEach(n => n.Expanded = true);

这真的很方便。