繁体   English   中英

递归函数内的StackOverFlowException

[英]StackOverFlowException inside a recursive function

我在数据库中有一个表,如下所示:

MenuItem
-------------
MenuItemId    1 --------+
MenuItemName            |
ParentId      * --------+

现在,我编写了一个递归函数来获取所有Parent MenuItems及其子级。

private ICollection<MenuItem> GetAllChildrenOfSpecificMenuItemRecursively(MenuItem menuItem, IEnumerable<MenuItem> menuItems)
{
    ICollection<MenuItem>  Children = null;
    foreach (MenuItem mi in menuItems)
    {
        if (mi.ParentMenuItemId != null)
        {
            if (mi.ParentMenuItemId == menuItem.MenuItemId)
            {
                Children.Add(mi);
            }
            else
            {
                return GetAllChildrenOfSpecificMenuItemRecursively(mi, menuItems);
            }
        }
    }

    return Children;
}

现在,我从另一个函数中调用它,如下所示:

public IEnumerable<MenuItem> GetAllParentMenuItemsWithChildren()
{
    List<MenuItem> MenuItems = new List<MenuItem>();
    IEnumerable<MenuItem> AllMenuItems = null;

    using (MaxContext entityContext = new MaxContext())
    {
        AllMenuItems = (from e in entityContext.MenuItemSet select e).ToList();

        foreach (MenuItem menuItem in entityContext.MenuItemSet)
        {
            if (menuItem.ParentMenuItemId == null)
            {
                menuItem.Children = GetAllChildrenOfSpecificMenuItemRecursively(menuItem, AllMenuItems);
                MenuItems.Add(menuItem);
            }
        }
    }

    return MenuItems;
}

但这给了我递归函数内部的stackoverflowException。 我确信我在该功能中犯了一个小错误。 有人可以指出那个错误吗?

您的GetAllChildrenOfSpecificMenuItemRecursively()总是与mi递归。 它应改为使用mi.ParentMenuItemId递归。

为什么总是将相同的menuItems colleciton传递给递归函数?

您的代码应类似于以下内容:

private IEnumerable<MenuItem> GetAllChildrenOfSpecificMenuItemRecursively(MenuItem menuItem)
{
    var children = new List<MenuItem>();
    foreach (MenuItem mi in menuItem.Children)
    { 
        // Why are you checking this?
        if (mi.ParentMenuItemId != null)
        {
            // Why are you checking this?
            if (mi.ParentMenuItemId == menuItem.MenuItemId)
            {
                children.Add(mi);
            }
            else
            {

                children.AddRange(GetAllChildrenOfSpecificMenuItemRecursively(mi))
            }
        }
    }

    return Children;
}

从方法名称来看,这就是它应该做的所有事情:

private IEnumerable<MenuItem> GetAllChildrenOfSpecificMenuItemRecursively(MenuItem menuItem)
{
    var children = new List<MenuItem>();
    if (menuItem.Children == null) return children;

    foreach (MenuItem mi in menuItem.Children)
    { 
       children.Add(mi);
       children.AddRange(GetAllChildrenOfSpecificMenuItemRecursively(mi));       
    }

    return Children;
}

编辑:

public class MenuItem
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }

    public virtual MenuItem Parent { get; set; }

    [InverseProperty("Parent")]
    public virtual ICollection<MenuItem> Children { get; set; }
}

我认为有一种更简单(甚至更快)的方法,无需使用递归。 像这样:

    public ICollection<MenuItem> GetMenuItemsAsTreeList()
    {
        AllMenuItems = entityContext.MenuItemSet.ToList();

        Dictionary<int, MenuItem> dic = AllMenuItems.ToDictionary(n => n.Id, n => n);

        List<MenuItem> rootMenuItems = new List<MenuItem>();

        foreach (MenuItem menuItem in AllMenuItems)
        {
            if (menuItem.ParentMenuItemId.HasValue)
            {
                MenuItem parent = dic[menuItem.ParentMenuItemId.Value];
                menuItem.ParentMenuItem = parent;
                parent.SubMenuItems.Add(menuItem);
            }
            else
            {
                rootMenuItems.Add(menuItem);
            }
        }

        return rootMenuItems;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM