2010-08-07 1 views
4

У меня есть класс Foo, как это:Создание стека <T> с анонимным типом

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

Можете ли вы форматировать код :) –

+0

уже сделано :) – 2010-08-07 07:28:51

+0

'Childs' читает немного странно, учитывая, что английский множественное число от«ребенок»является«дети»:) – AakashM

ответ

0

Вы можете просто положить его в метод как это:

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

Как насчет:

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

Это использует общий вывод типа для обработки T.

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); 
    } 
} 
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); 
     } 
    } 
} 
Смежные вопросы