Рекурсивная функция Линка и выход - PullRequest
0 голосов
/ 27 января 2010
 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 должна вызывать метод / расширение, но никогда не делает. Насколько я могу судить, линия ничего не делает!

Ответы [ 3 ]

2 голосов
/ 27 января 2010

Рекурсивный вызов никогда не выполняется, так как вы никогда не используете результат 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>() );
}   
2 голосов
/ 27 января 2010

Вы ничего не делаете с результатом выражения, и, вероятно, ленивая оценка не применяется. Если вы действительно хотите игнорировать результат выражения, по крайней мере попробуйте добавить ToArray () в конце;) Это должно привести к выполнению оценки и рекурсивно вызвать вашу функцию Traverse.

Преимущество решения Bojan (при условии, что вы действительно этого хотите, потому что оно возвращает результат, отличный от вашего первоначального), заключается в том, что фактическая ответственность за оценку переходит к клиенту метода Traverse. Поскольку в вашем случае это запросы в памяти, в любом случае, разница невелика, но если бы это были запросы к базе данных, то было бы более значительное снижение производительности (количество реальных запросов к базе данных) для помещения ToArray куда-либо.

0 голосов
/ 27 января 2010
 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;
        }
    }

Это дает желаемый результат, но не уверен, что он оптимален!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...