2010-01-27 2 views
0
public static IEnumerable<UIElement> Traverse(this UIElementCollection source) 
    { 
     source.OfType<Grid>().SelectMany(v => Traverse(v.Children)); 
     //This is the top level. 
     foreach (UIElement item in source) 
     { 
      yield return item; 
     } 
    } 

이 절대로 재귀 적으로 아무것도 반환하지 않습니다. 나는 집 주변에 있었다. Linq 체인은 함수/확장 메소드를 다시 호출해야하지만 결코 그렇지 않습니다. 그 선은 내가 말할 수있는 한 아무것도하지 않는다!재귀 Linq 함수 및 항복

+1

"집 주변"이란 의미는 무엇입니까? 이 영국 속어인가요? –

+1

속어 : 사방을 바라 보면서 내가 필요한 것을 찾지 못했습니다. – DavidA

답변

0
public static IEnumerable<UIElement> Traverse(this UIElementCollection source) 
    { 
     //This is the top level. 
     foreach (UIElement item in source.OfType<Grid>().SelectMany(v => Traverse(v.Children)).Concat(source.Cast<UIElement>())) 
     { 
      yield return item; 
     } 
    } 

이 아니라 그것이 비록 최적 반드시 원하는 결과입니다있다!

2

표현식의 결과에 아무런 변화가 없으므로 게으른 평가가 적용되지 않을 수 있습니다. 표현식의 결과를 무시하려면 적어도 끝 부분에 ToArray()를 추가하십시오.) 그러면 평가가 실행되고 재귀 적으로 Traverse 함수가 호출됩니다.

Bojan 솔루션의 이점 (실제 결과가 초기 결과와 다르므로 원하는 결과를 제공함)은 실제 평가 책임이 Traverse 메소드의 클라이언트로 이동된다는 것입니다. 어쨌든 이러한 경우는 메모리 내 쿼리이므로 차이가 크지는 않지만 데이터베이스 쿼리의 경우 ToArray를 어딘가에 두는 데 더 많은 성능 저하 (실제 데이터베이스 쿼리 수)가 있습니다.

+0

나는 표현이 평가되지 않는다는 점에서 당신과 함께합니다. 나는 그것을 평가할 필요가있다. VAR t = 처음에는 어쩌면? – DavidA

+0

var t는 실제로는 어딘가에서 iterating하지 않고 ToArray()에 의해 평가를 실시하지 않고도 평가되지 않습니다.) –

+0

좋은 점은 너무나 좋은 점입니다! 집행을 강요하는 ToArray는 강제로해야한다는 사실에 나를 알렸다. 그래서 결국에는 concat을 사용하여 표현식을 for for for 루프 구조로 덤프했습니다. – DavidA

2

SelectMany의 결과를 절대로 사용하지 않으므로 재귀 호출은 실행되지 않습니다. 이 메소드를 게으르게 만들 수 있고 클라이언트가 필요에 따라 의 결과를 얻도록하여 SelectMany의 결과를 현재 소스와 결합하도록 할 수 있습니다. 아마도이 같은 뭔가 작업 (하지 테스트)를 할 것입니다 :

public static IEnumerable<UIElement> Traverse(this UIElementCollection source) 
{ 
    var recursive_result = source.OfType<Grid>().SelectMany(v => Traverse(v.Children)); 
    return recursive_result.Concat(source.Cast<UIElement>()); 
} 
+0

이것은 나를 길로 인도했다! – DavidA