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