使用匿名类型</t>创建堆栈<t>

时间:2010-08-07 07:27:31

标签: c# .net anonymous-types

我有一个类Foo:

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

现在我想在Foo-Object上处理一些业务逻辑,并且所有孩子都是这样的:

 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 个答案:

答案 0 :(得分:7)

怎么样:

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

这使用泛型类型推断来处理T

答案 1 :(得分:1)

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

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 :(得分:1)

使用元组(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);
        }
    }
}

答案 3 :(得分:0)

您可以通过使用递归来简化代码,而不是将事物推送到临时堆栈和临时对象上。例如:

// (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);
    }
}