我有一个类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>
?当然我可以创建一个简单的类而不是匿名类(或更复杂的递归函数),但是如何在没有附加类的情况下解决这个问题呢?
答案 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);
}
}