C#get nesting Tree of Tree

时间:2013-11-08 22:40:13

标签: c# recursion nested

我们说我有两个班级:

public Foo
{
   public List<Foo> Childs { get; set; }
   public Bar BarObj { get; set; }
   public int Level { get; set; }
}

public Bar
{
   public List<Foo> Childs { get; set; }
}

现在我想从“Foo”对象的集合中获取嵌套级别

我目前的工作方法如下:

int currentLevel = 0;
public void ApplyNestingLevel(List<Foo> list)
{
    foreach(var item in list)
    {
        item.Level = currentLevel;
        if(item.Childs.Count > 0 || item.BarObj.Childs.Count > 0)
        {
            currentLevel++;
        }
        ApplyNestingLevel(item.Childs);
        ApplyNestingLevel(item.BarObj.Childs);
    }
}

我怎么能让这更“优雅/简单”?

2 个答案:

答案 0 :(得分:3)

存储对父项的引用,并使Level属性递归。

我在下面的代码示例中添加了一个示例和一些其他设计建议。希望这可以帮助。仅供参考,这与“四人帮”的Composite Pattern设计完全相同,对于那些认真考虑OOP的人来说,这应该是必读的。

  • DoFactory .NET Composite Pattern
  • Design Patterns: Elements of Reusable Object-Oriented Software, on Amazon.com

        public class Foo
        {
    
            public Foo(Foo parent = default(Foo))
            { 
                this.parent = parent;
                this.children = new List<Foo>();
            }
    
            private readonly Foo parent;
            private readonly List<Foo> children;
    
            public int Level { get { return ReferenceEquals(parent,null) ? 0 : parent.Level + 1; } }
    
            // don't expose the actual list... see below for why
            public IEnumerable<Foo> Children { get { foreach(Foo child in this.children) yield return child; } }
    
            //  instead of exposing the child object list
            //  declare an explicit method with any parameters 
            //  necessary.  this allows you to enforce the invariant 
            //  condition that all objects in a children collection
            //  will have their parent reference set to their 
            //  actual parent
            public void AddChild()
            {
                Foo newChild = new Foo(parent:this);
                this.children.Add(newChild);
            }
    
            //  if you need the ability to remove items as well, 
            //  you can expose a remove method too.  Just make 
            //  sure that you validate expected preconditions
            public int RemoveChild(Foo childToRemove)
            { 
                if(ReferenceEquals(childToRemove,null)) throw new ArgumentNullException("childToRemove");
                if(!ReferenceEquals(this,childToRemove.parent)) throw new ArgumentException("The object cannot be removed because the current object is not the correct parent.","childToRemove"); 
                return children.RemoveAll((Foo existentChild) => existentChild.Equals(childToRemove));
            }
    
    
        }
    

答案 1 :(得分:3)

public void ApplyNestingLevel(Foo f)
{
    ApplyNestingLevel(f, 0);
}


public void ApplyNestingLevel(Foo f, int level)
{
    if(f == null) { return; }
    f.Level = level
    if(f.Childs != null) {
        foreach(Foo child in f.Childs)
        {
            ApplyNestingLevel(child, level + 1);
        }
    }
    if(f.BarObj != null && f.BarObj.Childs != null) {
        foreach(Foo child in f.BarObj.Childs)
        {
            ApplyNestingLevel(child, level + 1);
        }
    }
}