C# 在自引用(父子)层次结构树中查找所有子体

C# 在自引用(父子)层次结构树中查找所有子体,c#,entity-framework,C#,Entity Framework,这与问题()类似。但是,我需要找到所有的后代,而不是找到所有的祖先 我正在修改Yacoub的方法,但只在一个分支中获得了所有子代 private IEnumerable<UserRole> FindAllChildrenRecursively(List<UserRole> allRoles, UserRole role) { var child = allRoles.FirstOrDefault(x => x.ParentId == role.Id)

这与问题()类似。但是,我需要找到所有的后代,而不是找到所有的祖先

我正在修改Yacoub的方法,但只在一个分支中获得了所有子代

    private IEnumerable<UserRole> FindAllChildrenRecursively(List<UserRole> allRoles, UserRole role)
{
    var child = allRoles.FirstOrDefault(x => x.ParentId == role.Id);

    if (child == null)
        return Enumerable.Empty<UserRole>();

    return new[] { child }.Concat(FindAllChildrenRecursively(allRoles, child));
}
private IEnumerable FindAllChildren递归(列出所有角色、用户角色)
{
var child=allRoles.FirstOrDefault(x=>x.ParentId==role.Id);
if(child==null)
返回可枚举的.Empty();
返回新的[]{child}.Concat(findallchildrenrecursive(allRoles,child));
}
我正在修改Yacoub的方法,但只在一个分支中获得了所有子代

这是因为这一行:

var child = allRoles.FirstOrDefault(x => x.ParentId == role.Id);
虽然它可能适合于寻找单亲父母,但不适合寻找多个子女

但是您不需要递归迭代器和
allRoles
列表上的多次迭代。您可以使用扩展方法创建快速查找结构,然后执行如下迭代:

private static IEnumerable<UserRole> FindAllChildren(List<UserRole> allRoles, UserRole role)
{
    var childrenByParentId = allRoles.ToLookup(r => r.ParentId);
    var stack = new Stack<IEnumerator<UserRole>>();
    var e = childrenByParentId[role != null ? role.Id : (int?)null].GetEnumerator();
    try
    {
        while (true)
        {
            while (e.MoveNext())
            {
                yield return e.Current;
                stack.Push(e);
                e = childrenByParentId[e.Current.Id].GetEnumerator();
            }
            if (stack.Count == 0) break;
            e.Dispose();
            e = stack.Pop();
        }
    }
    finally
    {
        e.Dispose();
        while (stack.Count > 0) stack.Pop().Dispose();
    }
}
private static IEnumerable<UserRole> FindAllChildren(List<UserRole> allRoles, UserRole role)
{
    var childrenByParentId = allRoles.ToLookup(r => r.ParentId);
    return childrenByParentId[role != null ? role.Id : (int?)null].Expand(r => childrenByParentId[r.Id]);
}
私有静态IEnumerable FindAllChildren(列出所有角色、用户角色)
{
var childrenByParentId=allRoles.ToLookup(r=>r.ParentId);
var stack=新堆栈();
var e=childrenByParentId[role!=null?role.Id:(int?)null].GetEnumerator();
尝试
{
while(true)
{
while(如MoveNext())
{
收益率,收益率,电流;
栈推(e);
e=childrenByParentId[e.Current.Id].GetEnumerator();
}
如果(stack.Count==0)中断;
e、 处置();
e=stack.Pop();
}
}
最后
{
e、 处置();
而(stack.Count>0)stack.Pop().Dispose();
}
}
更好的方法是(遵循该原则)利用以下通用树辅助方法:

公共静态类树
{
公共静态IEnumerable扩展(
此IEnumerable源(Func elementSelector)
{
var stack=新堆栈();
var e=source.GetEnumerator();
尝试
{
while(true)
{
while(如MoveNext())
{
var项目=e.当前;
收益回报项目;
变量元素=元素选择器(项目);
如果(elements==null)继续;
栈推(e);
e=elements.GetEnumerator();
}
如果(stack.Count==0)中断;
e、 处置();
e=stack.Pop();
}
}
最后
{
e、 处置();
而(stack.Count!=0)stack.Pop().Dispose();
}
}
}
像这样:

private static IEnumerable<UserRole> FindAllChildren(List<UserRole> allRoles, UserRole role)
{
    var childrenByParentId = allRoles.ToLookup(r => r.ParentId);
    var stack = new Stack<IEnumerator<UserRole>>();
    var e = childrenByParentId[role != null ? role.Id : (int?)null].GetEnumerator();
    try
    {
        while (true)
        {
            while (e.MoveNext())
            {
                yield return e.Current;
                stack.Push(e);
                e = childrenByParentId[e.Current.Id].GetEnumerator();
            }
            if (stack.Count == 0) break;
            e.Dispose();
            e = stack.Pop();
        }
    }
    finally
    {
        e.Dispose();
        while (stack.Count > 0) stack.Pop().Dispose();
    }
}
private static IEnumerable<UserRole> FindAllChildren(List<UserRole> allRoles, UserRole role)
{
    var childrenByParentId = allRoles.ToLookup(r => r.ParentId);
    return childrenByParentId[role != null ? role.Id : (int?)null].Expand(r => childrenByParentId[r.Id]);
}
私有静态IEnumerable FindAllChildren(列出所有角色、用户角色)
{
var childrenByParentId=allRoles.ToLookup(r=>r.ParentId);
返回childrenByParentId[role!=null?role.Id:(int?)null].Expand(r=>childrenByParentId[r.Id]);
}