我可以有一个返回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)

那应该是全部:-)