我正在编写一个简单的扩展方法来对一个控件及其所有子控件执行一个操作,我想知道是否需要担心两次遇到同一个控件。
安全:
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());
}
}