如何修改NestedControls方法以直接返回指定类型的容器控件?
问题
我现在用下面这个扩展方法获取容器里的所有嵌套控件:
public static IEnumerable<Control> NestedControls(this Control container, bool search_all_children = true) { var stack = new Stack<Control>(); stack.Push(container); do { var control = stack.Pop(); foreach (Control child in control.Controls) { yield return child; stack.Push(child); } } while (stack.Count > 0 && search_all_children); }
目前我只能通过这种方式筛选指定类型的控件,比如TextBox:
var textboxes = panel1.NestedControls().OfType<TextBox>().ToList();
我想修改这个方法,让它支持直接通过 panel1.NestedControls<TextBox>() 这样的调用获取指定类型的控件,该怎么改?
解决方案
你可以给方法加上泛型支持,直接在遍历过程中筛选目标类型,下面提供两种实用实现方式:
方式一:新增泛型重载(保留原方法兼容旧代码)
保留原来的无类型方法,新增一个泛型版本的重载,这样新旧调用逻辑都能正常运行:
// 原方法保持不变,兼容之前的调用 public static IEnumerable<Control> NestedControls(this Control container, bool search_all_children = true) { var stack = new Stack<Control>(); stack.Push(container); do { var control = stack.Pop(); foreach (Control child in control.Controls) { yield return child; stack.Push(child); } } while (stack.Count > 0 && search_all_children); } // 新增泛型扩展方法,直接返回指定类型控件 public static IEnumerable<T> NestedControls<T>(this Control container, bool search_all_children = true) where T : Control { var stack = new Stack<Control>(); stack.Push(container); do { var control = stack.Pop(); foreach (Control child in control.Controls) { // 直接匹配并转换为目标类型,符合条件才返回 if (child is T typedChild) { yield return typedChild; } stack.Push(child); } } while (stack.Count > 0 && search_all_children); }
调用示例:
// 获取所有TextBox控件 var textboxes = panel1.NestedControls<TextBox>().ToList(); // 获取所有Button控件 var buttons = panel1.NestedControls<Button>().ToList();
方式二:合并为泛型方法(通过包装兼容旧调用)
如果不想维护两个方法,可以把核心逻辑改成泛型实现,再套一层非泛型的包装方法:
// 泛型核心方法,限定T必须是Control子类 public static IEnumerable<T> NestedControls<T>(this Control container, bool search_all_children = true) where T : Control { var stack = new Stack<Control>(); stack.Push(container); do { var control = stack.Pop(); foreach (Control child in control.Controls) { if (child is T typedChild) { yield return typedChild; } stack.Push(child); } } while (stack.Count > 0 && search_all_children); } // 非泛型包装方法,兼容原有调用逻辑 public static IEnumerable<Control> NestedControls(this Control container, bool search_all_children = true) { return container.NestedControls<Control>(search_all_children); }
这种写法下,panel1.NestedControls()和panel1.NestedControls<TextBox>()都能正常使用。
关键说明
- 泛型约束
where T : Control能确保传入的类型是Control的子类,避免无效类型传入导致错误。 - 遍历过程中直接筛选转换,比先返回所有控件再用
OfType<T>更高效,减少了后续的集合操作开销。
内容的提问来源于stack exchange,提问作者Quince
相关产品推荐
相关产品推荐

