开发者

Recursive Linq Function and Yielding

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

This never returns anything recursively. I have been around the houses. The Linq chain should ca开发者_Go百科ll back into the function/extension method but never does. The line does nothing as far as I can tell!


You are not doing anything with the result of the expression and probably the lazy evaluation is not enforced. If you really want to ignore the result of the expression, at least try adding ToArray() at the end ;) That should enforce the evaluation and recursively call your Traverse function.

Advantage of Bojan's solution (provided that's what you really want because it returns a different result than your initial one), is that the actual evaluation responsibility is shifted to the client of the Traverse method. Because in your case these are in-memory queries anyway, it is not that big of a difference, but if these were database queries there is a more significant performance penalty (count of actual database queries) for putting ToArray somewhere.


The recursive call is never executed, as you never use the result of SelectMany. You can make this method lazy, and let the clients evaluate it when needed by combining the result of SelectMany with the current source. Perhaps something like this would do the job (not tested):

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


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

This has the desired result, not sure it is optimal though!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜