我可以有一个返回IEnumerator <T>的方法并在foreach循环中使用它吗?
时间:2020-03-05 18:38:00 来源:igfitidea点击:
我需要设置表单上每个文本框的高度,其中一些嵌套在其他控件中。我以为我可以做这样的事情:
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl) { foreach (Control control in rootControl.Controls) { if (control.Controls.Count > 0) { // Recursively search for any TextBoxes within each child control foreach (TextBox textBox in FindTextBoxes(control)) { yield return textBox; } } TextBox textBox2 = control as TextBox; if (textBox2 != null) { yield return textBox2; } } }
像这样使用它:
foreach(TextBox textBox in FindTextBoxes(this)) { textBox.Height = height; }
但是当然编译器会吐出它的虚拟对象,因为foreach期望使用IEnumerable而不是IEnumerator。
有没有一种方法可以不必使用GetEnumerator()方法创建单独的类?
解决方案
回答
正如编译器告诉那样,我们需要将返回类型更改为IEnumerable。这就是yield return语法的工作方式。
回答
// Generic function that gets all child controls of a certain type, // returned in a List collection private static List<T> GetChildTextBoxes<T>(Control ctrl) where T : Control{ List<T> tbs = new List<T>(); foreach (Control c in ctrl.Controls) { // If c is of type T, add it to the collection if (c is T) { tbs.Add((T)c); } } return tbs; } private static void SetChildTextBoxesHeight(Control ctrl, int height) { foreach (TextBox t in GetChildTextBoxes<TextBox>(ctrl)) { t.Height = height; } }
回答
如果返回IEnumerator,则每次调用该方法时它将是一个不同的枚举器对象(就像在每次迭代中重置枚举器一样)。如果返回IEnumerable,则可以使用yield语句基于该方法枚举foreach。
回答
只是为了澄清
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
更改为
private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)
那应该是全部:-)