我正在编写一个简单的扩展方法来对控件及其所有子控件执行操作,我想知道是否必须担心两次遇到同一个控件。
安全:
public static void Traverse(this Control control, Action<Control> action)
{
Traverse(control, action, new HashSet<control>());
}
private static void Traverse(this Control control, Action<Control> action, HashSet<Control> handled)
{
handled.Add(control);
foreach (Control child in control.Controls)
if (!handled.Contains(child))
Traverse(child, action, handled);
action.Invoke(control);
}
可能不安全:
public static void Traverse(this Control control, Action<Control> action)
{
foreach (Control child in control.Controls)
Traverse(child, action, handled);
action.Invoke(control);
}
哈希集是否需要保证此代码的安全?它只需要对每个控件调用一次操作,并且不能进入无限循环。父子控件的结构是否使我不需要担心这个问题?
用法:
this.Traverse(o => o.SuspendLayout());
// Do lots of UI changes
this.Traverse(o => o.ResumeLayout());
(可能)全面的方法:
public static class ControlExtensions
{
public static void Traverse(this Control control, Action<Control> action)
{
Traverse(control, action, TraversalMethod.DepthFirst);
}
public static void Traverse(this Control control, Action<Control> action, TraversalMethod method)
{
switch (method)
{
case TraversalMethod.DepthFirst:
TraverseDepth(control, action);
break;
case TraversalMethod.BreadthFirst:
TraverseBreadth(control, action);
break;
case TraversalMethod.ReversedDepthFirst:
TraverseDepthReversed(control, action);
break;
case TraversalMethod.ReversedBreadthFirst:
TraverseBreadthReversed(control, action);
break;
}
}
private static void TraverseDepth(Control control, Action<Control> action)
{
Stack<Control> controls = new Stack<Control>();
Queue<Control> queue = new Queue<Control>();
controls.Push(control);
while (controls.Count != 0)
{
control = controls.Pop();
foreach (Control child in control.Controls)
controls.Push(child);
queue.Enqueue(control);
}
while (queue.Count != 0)
action.Invoke(queue.Dequeue());
}
private static void TraverseBreadth(Control control, Action<Control> action)
{
Queue<Control> controls = new Queue<Control>();
Queue<Control> queue = new Queue<Control>();
controls.Enqueue(control);
while (controls.Count != 0)
{
control = controls.Dequeue();
foreach (Control child in control.Controls)
controls.Enqueue(child);
queue.Enqueue(control);
}
while (queue.Count != 0)
action.Invoke(queue.Dequeue());
}
private static void TraverseDepthReversed(Control control, Action<Control> action)
{
Stack<Control> controls = new Stack<Control>();
Stack<Control> stack = new Stack<Control>();
controls.Push(control);
while (controls.Count != 0)
{
control = controls.Pop();
foreach (Control child in control.Controls)
controls.Push(child);
stack.Push(control);
}
while (stack.Count != 0)
action.Invoke(stack.Pop());
}
private static void TraverseBreadthReversed(Control control, Action<Control> action)
{
Queue<Control> controls = new Queue<Control>();
Stack<Control> stack = new Stack<Control>();
controls.Enqueue(control);
while (controls.Count != 0)
{
control = controls.Dequeue();
foreach (Control child in control.Controls)
controls.Enqueue(child);
stack.Push(control);
}
while (stack.Count != 0)
action.Invoke(stack.Pop());
}
}
最佳答案
每个 child 都有一个 parent ,因此无需担心。
关于c# - 遍历子控件时避免无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3215166/