代码之家  ›  专栏  ›  技术社区  ›  user410989

创建匿名类型的堆栈

  •  4
  • user410989  · 技术社区  · 14 年前

     class Foo
     {
      public int id{get;set;}
      public IEnumerable<Foo> Childs;
           //some other properties
     }
    

    现在我想在Foo对象及其所有子对象上处理一些业务逻辑,如下所示:

     public void DoSomeWorkWith(Foo x)
     {
      var firstItem = new {level = 0, item = x};
      var s = new Stack<?>(?); //What type to use?
      s.Push(firstItem);
      while(s.Any())
      {
        var current = s.Pop();
        DoSomeBusiness(current.item);
        DoSomeMoreBusiness(current.item);
        Log(current.level, current.item.id);
        foreach(Foo child in current.item.Childs)
           s.Push(new {level = current.level + 1, item = child});
       }
    }
    

    我需要跟踪孩子们的(相对)水平/深度。 Stack<T> 匿名类型?当然,我可以创建一个简单的类,而不是匿名类型(或者更复杂的递归函数),但是如何在没有额外类的情况下解决这个问题呢?

    4 回复  |  直到 14 年前
        1
  •  1
  •   sloth JohnnBlade    14 年前

    你可以把它放到这样一个方法中:

    public Stack<T> CreateStackWithInitialItem<T>(T initialItem)
    {
        var s = new Stack<T>();
        s.Push(initialItem);
        return s;
    }
    

    public void DoSomeWorkWith(Foo x)
    {
        var s = CreateStackWithInitialItem(new {level = 0, item = x});
        while(s.Any())
        {
            ...
        }
    }
    
        2
  •  7
  •   Marc Gravell    14 年前

    怎么样:

    public static Stack<T> CreateEmptyStack<T>(T template) {
        return new Stack<T>();
    }
    ...
    var stack = CreateEmptyStack(firstItem);
    

    它使用泛型类型推断来处理 T .

        3
  •  1
  •   Roland Sommer    14 年前

    使用元组怎么样( System.Tuple<> )而不是匿名类型?

    public void DoSomeWorkWith(Foo x)
    {
        var firstItem = new Tuple<int, Foo>(0, x);
        var s = new Stack<Tuple<int, Foo>>();
        s.Push(firstItem);
        while (s.Any())
        {
            var current = s.Pop();
            DoSomeBusiness(current.Item2);
            DoSomeMoreBusiness(current.Item2);
            Log(current.Item1, current.Item2.id);
            foreach (Foo child in current.Item2.Childs)
                s.Push(new Tuple<int, Foo>(current.Item1 + 1, child));
        }
    }
    

    System.Dynamic.ExpandoObject .

    public void DoSomeWorkWith(Foo x)
    {
        dynamic firstItem = new ExpandoObject();
        firstItem.level = 1;
        firstItem.item = x;
    
        var s = new Stack<dynamic>();
        s.Push(firstItem);
        while (s.Any())
        {
            var current = s.Pop();
            DoSomeBusiness(current.item);
            DoSomeMoreBusiness(current.item);
            Log(current.level, current.item.id);
            foreach (Foo child in current.item.Childs)
            {
                dynamic next = new ExpandoObject();
                next.level = current.level + 1;
                next.item = child;
                s.Push(next);
            }
        }
    }
    
        4
  •  0
  •   Jacob    14 年前

    // (If you're not using C# 4, you can replace the default level with a function
    // overload or just remove the default value)
    
    void ProcessFooRecursive(Foo foo, int level = 0) 
    {
        DoSomeBusiness(foo);
        DoSomeMoreBusiness(foo);
        Log(level, foo.id);
    
        var newDepth = level + 1;
        foreach (var child in foo.Childs)
        {
            ProcessFooRecursive(child, newDepth);
        }
    }