广度优先搜索C#Control Collection

KP.*_*KP. 0 c# asp.net queue recursion breadth-first-search

我正在尝试编写一个扩展方法,System.Web.UI.Control为其搜索ControlCollection特定的实例Type,并返回找到的第一个实例.深度优先很简单,但我想首先搜索广度,以便更高的集合优先.

我当前的方法存在缺陷并将提前退出,在整个搜索未完成的某些情况下返回null.我希望我接近正确的解决方案,但需要一些新的眼睛.有什么建议?

public static T FindFirstControlOfType<T>(this Control rootControl, bool searchRecursively) where T : Control
{
    // list for container controls
    List<Control> controlsWithChildren = new List<Control>();

    // iterate the current control collection first
    foreach (Control child in rootControl.Controls)
    {
        if (child.GetType().IsAssignableFrom(typeof(T)))
        {
            return (T)child;
        }

        // track those controls containing children
        if (child.HasControls())
        {
            controlsWithChildren.Add(child);
        }
    }

    // if recursion is enabled, search the child nodes
    if (searchRecursively)
    {
        foreach (Control control in controlsWithChildren)
        {
            return FindFirstControlOfType<T>(control, true);
        }
    }

    // if never found, return null
    return null;
}
Run Code Online (Sandbox Code Playgroud)

编辑 - 基于明确答案的工作解决方案,对任何感兴趣的人:

public static T FindFirstControlOfType<T>(this Control rootControl, bool searchNestedControls) where T : Control
{
    Queue<Control> queue = new Queue<Control>();

    EnqueueChildControls(queue, rootControl);
    while (queue.Count > 0)
    {
        Control current = queue.Dequeue();

        if (current.GetType() == typeof(T))
        {
            return (T)current;
        }

        if (searchNestedControls)
        {
            EnqueueChildControls(queue, current);
        }
    }
    return null;

}

private static void EnqueueChildControls(Queue<Control> queue, Control control)
{
    foreach (Control current in control.Controls)
    {
        queue.Enqueue(current);
    }
}
Run Code Online (Sandbox Code Playgroud)

And*_*ker 5

广度优先搜索(伪代码)

Queue fringe 

fringe.Enqueue(rootControl)

while(fringe.Count > 0)
{
    current = fringe.Dequeue()
    Visit(current)
    fringe.EnqueueAll(current.Children)
}
Run Code Online (Sandbox Code Playgroud)

广度优先搜索不需要递归.

Visit是你想用当前对象做什么的.如果你正在寻找某些东西那么Visit意味着:if(current matches criteria) return current

更新:工作示例:https://gist.github.com/1960108