Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 递归函数中的StackOverFlowException_C#_Recursion - Fatal编程技术网

C# 递归函数中的StackOverFlowException

C# 递归函数中的StackOverFlowException,c#,recursion,C#,Recursion,我在数据库中有一个表,如下所示: MenuItem ------------- MenuItemId 1 --------+ MenuItemName | ParentId * --------+ public IEnumerable<MenuItem> GetAllParentMenuItemsWithChildren() { List<MenuItem> MenuItems = new List<MenuItem&

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

MenuItem
-------------
MenuItemId    1 --------+
MenuItemName            |
ParentId      * --------+
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;
}
现在我已经编写了一个递归函数来获取所有父菜单项及其子菜单项

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;
}
private ICollection GetAllChildrenofSpecificMenuItem递归(MenuItem MenuItem,IEnumerable menuItems)
{
ICollection Children=null;
foreach(menuItems中的MenuItem mi)
{
如果(mi.ParentMenuItemId!=null)
{
if(mi.ParentMenuItemId==menuItem.MenuItemId)
{
儿童。添加(mi);
}
其他的
{
递归返回GetAllChildrenofSpecificMenuItem(mi,menuItems);
}
}
}
返回儿童;
}
现在,我从另一个函数调用它,如下所示:

MenuItem
-------------
MenuItemId    1 --------+
MenuItemName            |
ParentId      * --------+
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;
}
public IEnumerable GetAllParentMenuItemsWithChildren()
{
List MenuItems=新列表();
IEnumerable AllMenuItems=null;
使用(MaxContext entityContext=new MaxContext())
{
AllMenuItems=(从entityContext.MenuItemSet中的e选择e).ToList();
foreach(entityContext.MenuItemSet中的MenuItem MenuItem)
{
if(menuItem.ParentMenuItemId==null)
{
menuItem.Children=GetAllChildrenofSpecificMenuItem递归(menuItem,AllMenuItems);
MenuItems.Add(menuItem);
}
}
}
返回菜单项;
}

但是它在递归函数中给了我stackoverflowException。我确信我在这个功能上犯了一个小错误。有人能指出这个错误吗?

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

您的
GetAllChildrenofSpecificMenuItemRecursely()
始终使用
mi
递归。它应该使用
mi.ParentMenuItemId
递归。

为什么总是将相同的
menuItems
集合传递到递归函数中

您的代码应该大致如下:

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 GetAllChildrenofSpecificMenuItem递归(MenuItem MenuItem)
{
var children=新列表();
foreach(MenuItem.Children中的MenuItem mi)
{ 
//你为什么要查这个?
如果(mi.ParentMenuItemId!=null)
{
//你为什么要查这个?
if(mi.ParentMenuItemId==menuItem.MenuItemId)
{
儿童。添加(mi);
}
其他的
{
AddRange(GetAllChildrenOfSpecificMenuItemRecursively(mi))
}
}
}
返回儿童;
}
从方法名称来看,它应该做的就是:

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;
}
private IEnumerable GetAllChildrenofSpecificMenuItem递归(MenuItem MenuItem)
{
var children=新列表();
if(menuItem.Children==null)返回子项;
foreach(MenuItem.Children中的MenuItem mi)
{ 
儿童。添加(mi);
AddRange(GetAllChildrenOfSpecificMenuItemRecursively(mi));
}
返回儿童;
}
编辑:

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; }
}
公共类菜单项
{
[数据库生成(DatabaseGeneratedOption.Identity)]
公共int Id{get;set;}
公共字符串名称{get;set;}
public int ParentId{get;set;}
公共虚拟菜单项父项{get;set;}
[反向财产(“母公司”)]
公共虚拟ICollection子项{get;set;}
}

为什么总是将相同的
菜单项
集合传递给递归函数

您的代码应该大致如下:

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 GetAllChildrenofSpecificMenuItem递归(MenuItem MenuItem)
{
var children=新列表();
foreach(MenuItem.Children中的MenuItem mi)
{ 
//你为什么要查这个?
如果(mi.ParentMenuItemId!=null)
{
//你为什么要查这个?
if(mi.ParentMenuItemId==menuItem.MenuItemId)
{
儿童。添加(mi);
}
其他的
{
AddRange(GetAllChildrenOfSpecificMenuItemRecursively(mi))
}
}
}
返回儿童;
}
从方法名称来看,它应该做的就是:

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;
}
private IEnumerable GetAllChildrenofSpecificMenuItem递归(MenuItem MenuItem)
{
var children=新列表();
if(menuItem.Children==null)返回子项;
foreach(MenuItem.Children中的MenuItem mi)
{ 
儿童。添加(mi);
AddRange(GetAllChildrenOfSpecificMenuItemRecursively(mi));
}
返回儿童;
}
编辑:

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; }
}
公共类菜单项
{
[数据库生成(DatabaseGeneratedOption.Identity)]
公共int Id{get;set;}
公共字符串名称{get;set;}
public int ParentId{get;set;}
公共虚拟菜单项父项{get;set;}
[反向财产(“母公司”)]
公共虚拟ICollection子项{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;
    }
public ICollection GetMenuItemsAsTreeList()
{
AllMenuItems=entityContext.MenuItemSet.ToList();
Dictionary dic=AllMenuItems.ToDictionary(n=>n.Id,n=>n);
List rootMenuItems=新列表();
foreach(所有菜单项中的菜单项菜单项)
{
if(menuItem.ParentMenuItemId.HasValue)
{
MenuItem parent=dic[MenuItem.ParentMenuItemId.Value];
menuItem.ParentMenuItem=父项;
父菜单项、子菜单项、添加菜单项;
}
其他的
{
rootMenuItems.Add(menuItem);
}
}
返回rootMenuItems;
}

我认为有一种更简单(也许更快)的方法,不用使用递归。大概是这样的:

    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;
    }