我希望获得树状结构中所有成员的列表(包含n个包含n个组的组的组等等。根元素也包含成员。
架构:
Group
Group
Member
Member
Member
Group
Member
Group
Member
Member
Group
Group
Group
Member
现在我的代码看起来像这样:
public IEnumerable<Member> GetMembers() {
foreach(var member in this.MemberCollection) {
yield return member;
}
foreach(var group in this.GroupCollection) {
GetMembers();
}
}
不幸的是,这不起作用 - “GetMembers()”调用只是“被忽略” - 是否有“解决方法”?
我已经找到了与此类似的解决方案:
public IEnumerable<Member> GetMembers() {
foreach(var group in this.GroupCollection) {
foreach(var member in GetMembers()) {
yield return member;
}
}
}
答案 0 :(得分:3)
要递归,你的方法应该带一个参数(否则递归永远不会停止):
public IEnumerable<Member> GetMembers(Group group) {
foreach(var member in group.MemberCollection) {
yield return member;
}
foreach(var subGroup in group.GroupCollection) {
foreach (var member in GetMembers(group)) {
yield return member;
}
}
}
但是,对于深层嵌套的层次结构,递归迭代器块往往效率很低。更好的方法是使用迭代而不是递归。要像递归方法那样进行深度优先遍历,您可以这样做:
public IEnumerable<Member> GetMembers() {
var stack = new Stack<Group>();
stack.Push(this);
while (stack.Count > 0) {
var group = stack.Pop();
foreach(var member in group.MemberCollection) {
yield return member;
}
foreach(var subGroup in group.GroupCollection) {
stack.Push(subGroup);
}
}
}
要获得广度优先遍历,请使用队列而不是堆栈。
答案 1 :(得分:1)
简单地调用yield
不会从调用方法返回其结果,如果它没有被枚举(并且它使用public IEnumerable<Member> GetMembers() {
foreach(var member in this.MemberCollection) {
yield return member;
}
foreach(var group in this.GroupCollection) {
foreach(var member in group.GetMembers()) {
yield return member;
}
}
}
),它也不会被调用,而是你可以这样做:
yield
在方法中使用IEnumerable<>
时,编译器实际上会生成一个单独的类来实现{{1}}以返回结果 - 该类只是懒惰地进行枚举,所以如果你实际上没有迭代结果,它们没有被评估(如果您依赖于可能在其他地方发生变异的属性的状态,那么在您枚举它们之前也不会对它们进行评估)