使用匿名类型创建 Stack<T>

5

I have the a class Foo like this:

 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>?当然,我可以创建一个简单的类来代替匿名类型(或更复杂的递归函数),但如何在不使用额外类的情况下解决此问题?

你能否请格式化你的代码 :) - Marcus Johansson
“Childs” 这个词读起来有点奇怪,因为英语中 “child” 的复数形式是 “children” :) - AakashM
4个回答

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

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


2

你可以把它放进一个像这样的方法中:

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())
    {
        ...
    }
}

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接