Почему эта рекурсия не работает в C #? - PullRequest
3 голосов
/ 11 февраля 2010
public static bool AllNodesChecked(TreeNodeCollection nodes)        
{
    foreach (TreeNode node in nodes)
    {
        if (!node.Checked)
        {
            return false;
        }
        AllNodesChecked(node.Nodes);
    }
    return true;
}

Тестовое дерево

A1(checked) -> B1(unchecked)
A2(checked)
A3(checked)

но не возвращается, когда попадает на узел B1.

РЕДАКТИРОВАТЬ: Спасибо всем за помощь мой усталый мозг. Рекурсию следует проводить только в начале дня после холодного душа.

Ответы [ 6 ]

20 голосов
/ 11 февраля 2010

Вы игнорируете возвращаемое значение AllNodesChecked в рекурсивном вызове:

public static bool AllNodesChecked(TreeNodeCollection nodes)        
{
    foreach (TreeNode node in nodes)
        if (!node.Checked || !AllNodesChecked(node.Nodes))
           return false;
    return true;
}

Оператор return возвращает только метод current в стеке вызовов непосредственному вызывающему. Он неожиданно не возвращается из всех других вызовов выше в стеке вызовов.

8 голосов
/ 11 февраля 2010

Изменение:

AllNodesChecked(node.Nodes); 

Кому:

if(!AllNodesChecked(node.Nodes))
    return false;
7 голосов
/ 11 февраля 2010

Я бы выбрал здесь немного другой подход. Я бы сначала написал код, который превращает ваше дерево (которое, как я полагаю, действительно дерево, а не произвольный граф) в последовательность узлов. Что-то вроде:

static IEnumerable<Node> AllNodes(this Node node)
{
    var stack = new Stack<Node>();
    stack.Push(node);
    while(stack.Count > 0)
    {
        var current = stack.Pop();
        yield return current;
        foreach(var child in current.Nodes)
            stack.Push(child);
    }
}

и теперь вы можете использовать операторы последовательности:

bool allChecked = root.AllNodes().All(x=>x.Checked);

Нет рекурсии, нет проблем.

3 голосов
/ 11 февраля 2010

Вы не оцениваете результат рекурсивного вызова для проверки дочерних узлов.

2 голосов
/ 11 февраля 2010

Попробуйте это:

public static bool AllNodesChecked(TreeNodeCollection nodes)         
{ 
    foreach (TreeNode node in nodes) 
    { 
        if (node.Checked == false || !AllNodesChecked(node.Nodes)) 
        { 
            return false; 
        } 
    } 
    return true; 
} 
0 голосов
/ 02 августа 2011

Я должен добавить свои два цента .... Учиться функциональному программированию ИМХО.

public static bool AllNodesChecked(TreeNodeCollection nodes)  
{
    return nodes.All(i => i.Checked && AllNodesChecked(i.Nodes));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...