2009-05-01 6 views
1

私は現在、IEnumerable<T>を実装するクラスを作成して、ParentIdプロパティを通じて互いに参照を持つオブジェクトのフラットなリストから階層を構築しようとしています。私はyield文については、だから、このlinqの "Select New"は評価/負荷をトリガしますか?

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

怠惰な - 一度にすべてではありません。

どちらのアプローチは、同等でなければなりません - しかし、.Where(...).Select(...)チェーンを構築するためのコードのみ - - あなたは結果を反復処理を開始するまで、それは実際に行を処理しません唯一の違いはyield returnせずに、一部コードがすぐに実行するということです。

また、データソースによっては、TSQLジェネレータが不要な列をスキップできるため、実際にはLINQからSQLへのバックエンドを使用する方が効率的です。

関連する問題