简体   繁体   中英

recursive function call in foreach throwing system.stackoverflowexception

I am getting a System.StackOverflowException: 'Exception of type 'System.StackOverflowException' was thrown.' message.

My code as follows, Here I want to assign value to a variable recursively based on the condition and return the list.

public class FancyTree
{
    public string title { get; set; }
    public string key { get; set; }     
    public List<FancyTree> children { get; set; }
}

For example the FancyTree Class produces the output like parent->child or parent->parent->child or parent->parent->parent->child just like the Treeview structure.

public JsonResult EmployeesTree()
{  
   var output = converttoFancyTree(db.Database.GetEmployees(true));
   return Json(output, JsonRequestBehavior.AllowGet);
}
public List<FancyTree> converttoFancyTree(List<EmpTable> emps)
    {
        var output = new List<FancyTree>();
        foreach (var emp in emps)
        {
            var fancyTreeItem = new FancyTree();
            fancyTreeItem.key = emp.EMP_ID.ToString();
            fancyTreeItem.title = emp.EMP_NAME;

            if (!string.IsNullOrEmpty(emp.TEAM))
                {
                    //var empIDs = emp.TEAM?.Split(',')?.Select(Int32.Parse)?.ToList();
                    var tms = emp.TEAM.Split(',');
                    if (tms.Length > 0) {
                        var empIDs = new List<int>();
                        foreach (var t in tms) 
                        {
                            empIDs.Add(int.Parse(t));
                        }
                        var TeamMembers = emps.Where(x => empIDs.Contains(x.EMP_ID)).ToList();
                        if (TeamMembers.Count > 0)
                        {
                            var childrens = converttoFancyTree(TeamMembers);
                            fancyTreeItem.children = childrens;
                        }   
                    }                        
                }
            output.Add(fancyTreeItem);
        }
        return output;
    }

I would assume your input is in the form of a plain list of objects, where each object contains the IDs of all the children, and you want to convert this to an object representation, ie something like:

public class Employee{
    public int Id {get;}
    public List<int> SubordinateIds {get;}
}

public class EmployeeTreeNode{
    public IReadOnlyList<EmployeeTreeNode> Subordinates {get;} ;
    public int Id {get;}
    public EmployeeTreeNode(int id, IEnumerable<EmployeeTreeNode> subordinates){
        Id = id;
        Subordinates = subordinates;
}

To convert this to a tree representation we can start by finding the roots of the tree, ie employees that are not subordinate to anyone.

var allSubordinates = allEmployees.SelectMany(e => e.SubordinateIds).ToList();
var allRoots = allEmployees.Select(e => e.Id).Except(allSubordinates);

We then need an efficient way to find a specific employee by the Id, ie a dictionary:

var employeeById = allEmployees.ToDictionary(e => e.Id, e => e.SubordinateIds);

We can then finally do the actual recursion, and we can create a generic helper method to assist:

public static TResult MapChildren<T, TResult>(
    T root, 
    Func<T, IEnumerable<T>> getChildren,
    Func<T,  IEnumerable<TResult>, TResult> map)
{
    return RecurseBody(root);
    TResult RecurseBody(T item) => map(item,  getChildren(item).Select(RecurseBody));
}
...

var tree = allRoots.Select(r => MapChildren(
    r, 
    id => employeeById[id], 
    (id, subordinates) => new EmployeeTreeNode(id, subordinates)));

This will recurse down to any employee without any subordinates, create EmployeeTreeNode for these, and then eventually traverse up the tree, creating node objects as it goes.

This assumes that there are no "loops" in the tree. If that is the case you actually have a graph, and the code will crash. One way to detect this would be to add all visited employees to a HashSet, and ignore these if they occur again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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