我有一个看起来像这样的区类:
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“。
这是否涉及收益率报表(我从未完全理解)? 可以一行完成吗?
答案 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);
这真的很方便。