2010-01-27 72 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

“围绕房屋”是什么意思?这是英国俚语吗? – 2010-01-27 15:10:24

+1

俚语:尝试寻找无处不在,找不到我需要的东西。 – DavidA 2010-02-02 14:00:53

回答

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函数。

博的解决方案的优势(前提就是你真正想要的,因为它不是返回一个不同的结果,你最初的一个),是实际评估的责任转移到遍历方法的客户端。因为在你的情况下,这些都是内存查询,但这并不是什么大不了的,但如果这些是数据库查询,那么将ToArray放在某处会有更显着的性能损失(实际数据库查询的计数)。

+0

我对你很友善,因为表达不被评估。我需要它来评估。 Var t =在开始时可能? – DavidA 2010-01-27 14:43:53

+0

变种t是不够的,实际上并没有迭代它的地方,或ToArray的(),它仍然无法评价执行评估;) – 2010-01-27 14:47:43

+0

好explination因此获得一些积分! ToArray强制执行标记我的事实,我需要强制它。所以最后使用了concat并将表达式转储到了for循环结构中。 – DavidA 2010-01-27 15:09:04

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 2010-01-27 15:09:36