2009-05-01 3 views
1

В настоящее время я пытаюсь создать класс, который реализует IEnumerable<T>, чтобы построить иерархию из плоского списка объектов, имеющих ссылки друг на друга через свойство ParentId. Я хотел бы написать свободно интерфейс для этого, так что я могу сделать что-то вроде этого«Выбирает новый» в linq запускает оценку/нагрузку?

IEnumerable<Tab> tabs = GetTabs(); 

IEnumerable<TabNode> tabNodes = tabs.AsHierarchy().WithStartLevel(2).WithMaxDepth(5); 

Итак, об утверждении выхода, я задаюсь вопросом, могу ли я сделать что-то вроде этого в моем NodeHierarchy : IEnumerable<TabNode> классе:

private IEnumerable<TabNode> _nodes; 

public NodeHierarchy(IEnumerable<Tab> tabs) 
{ 
    _nodes = CreateHierarchy(tabs); 
} 

public IEnumerable<TabNode> CreateHierarchy(IEnumerable<Tab> tabs) 
{ 
    /* About this block: I'm trying to find the top level 
    nodes of the first tab collection, maybe this is done poorly? */ 
    var tabIds = tabs.Select(t => t.TabID); 
    IEnumerable<TabNode> nodes = from tab in tabs 
          where !tabIds.Contains(tab.ParentId) 
           select new TabNode { 
              Tab = node, 
              ChildNodes = CreateHierarchy(tabs, node.TabID, 1), 
              Depth = 1 }; 
    return nodes; 
} 

, или я должен был бы сделать что-то вроде этого:

private IEnumerable<TabNode> _nodes; 

public NodeHierarchy(IEnumerable<Tab> tabs) 
{ 
    _nodes = CreateHierarchy(tabs); 
} 

public IEnumerable<TabNode> CreateHierarchy(IEnumerable<Tab> tabs) 
{ 
var tabIds = tabs.Select(t => t.TabID); 
IEnumerable<Tab> startingNodes = from tab in tabs 
           where !tabIds.Contains(tab.ParentId) 
           select tab; 

foreach(Tab node in startingNodes) 
{ 
    yield return 
    new TabNode() 
     { 
     Tab = node, 
     ChildNodes = CreateHierarchy(tabs, node.TabID, 1), 
     Depth = 1 
    }; 
} 
+0

Не могли бы вы переформатировать свой код, используя пробелы вместо вкладок? На данный момент это довольно непроницаемо. –

+0

Да, я знаю, спасибо, я над этим работаю ... работа с копией не работала здесь :) – kitsune

+0

Должно быть исправлено сейчас ... – kitsune

ответ

2

нет, select new не будет вызывать оценку. Это будет отображать на вызов:

.Select(tab => new TabNode {...}) 

И заметьте, что Select (для LINQ к объектам, по крайней мере), по существу, что-то вроде:

public static IEnumerable<TDest> Select<TSource,TDest>(
    this IEnumerable<TSource> source, 
    Func<TSource,TDest> selector) 
{ 
    foreach(TSource item in source) 
    { 
     yield return selector(source); 
    } 
} 

Ключевой момент здесь в том, что он оценивает ленивый - не все сразу.

Либо подход должен быть сопоставим - с той лишь разницей, что без yield return, некоторые код будет работать сразу - но только код, чтобы построить .Where(...).Select(...) цепь - это фактически не будет обрабатывать строки, пока вы не начнете переборе результат ,

Кроме того, в зависимости от источника данных этот подход может быть более эффективным - например, с использованием LINQ to SQL, поскольку генератор TSQL может пропускать ненужные столбцы.

Смежные вопросы