2009-05-01 3 views
1

현재 ParentId 속성을 통해 서로에 대한 참조가있는 객체의 플랫 목록에서 계층 구조를 구성하기 위해 IEnumerable<T>을 구현하는 클래스를 만들려고합니다. 내가 yield 문에 대해, 그래서이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 평가를 트리거하지 않습니다. 이에 대한 호출로 매핑됩니다 : 여기

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

중요한 점은 평가하는 것 :

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

그리고주의 (LINQ - 투 - 객체, 적어도에 대한) 본질적으로 같은 것입니다 Select 그 게으른 - 한 번에 모든 것이 아닙니다.

어느 접근 방식은 비교해야합니다 -하지만 코드가 .Where(...).Select(...) 체인을 구축하기 위해 - - 유일한 차이점은 yield return없이, 일부 코드를 즉시 실행하는 것입니다 당신이 결과를 반복 시작할 때까지 실제로 행을 처리하지 않습니다 .

또한 데이터 소스에 따라 TSQL 생성기가 불필요한 열을 건너 뛸 수 있으므로 LINQ-SQL 백엔드를 사용하는 것과 같은 방식이 실제로 더 효율적일 수 있습니다.