質問

現在、ParentIdプロパティを介して相互に参照しているオブジェクトのフラットリストから階層を構築するために、 IEnumerable< T> を実装するクラスを作成しようとしています。私はこのために流fluentなインターフェイスを書きたいので、このようなことをすることができます

IEnumerable<Tab> tabs = GetTabs();

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

それで、yieldステートメントについて、 NodeHierarchy:IEnumerable&lt; TabNode&gt; クラス内で次のようなことができるかどうか疑問に思います:

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
    };
}
役に立ちましたか?

解決

いいえ、 select new は評価をトリガーしません。これは、次の呼び出しにマッピングされます。

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

そして Select (少なくともLINQ-to-Objectsの場合)は基本的に次のようなものであることに注意してください:

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 がなければ、一部のコードがすぐに実行されることですが、をビルドするコードのみです。 (...)。Select(...)チェーン-結果の反復を開始するまで、実際には行を処理しません。

さらに、データソースによっては、TSQLジェネレーターが不要な列をスキップできるため、その方法は実際にはより効率的です(たとえば、LINQ-to-SQLバックエンドの場合)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top