[英]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.