我可以有一个方法返回IEnumerator <T>并在foreach循环中使用它?

我需要设置窗体上每个文本框的高度,其中一些嵌套在其他控件中。我以为我可以做这样的事情:

private static IEnumerator 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()方法创建单独的类?

0
额外 编辑
意见: 2
实际上, foreach 根本不期望一个 IEnumerable (也不是一个 IEnumerable )。它只希望有一个具有 GetEnumerator 方法的东西。该方法反过来不一定返回 IEnumeratorIEnumerator ?它只需要返回具有 MoveNext()方法和 Current 属性的内容。
额外 作者 Timwi,

5 答案

只是为了澄清

private static IEnumerator FindTextBoxes(Control rootControl)

更改

private static IEnumerable FindTextBoxes(Control rootControl)

这应该是全部:-)

0
额外
// Generic function that gets all child controls of a certain type, 
// returned in a List collection
private static List GetChildTextBoxes(Control ctrl) where T : Control{
    List tbs = new List();
    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(ctrl)) {
        t.Height = height;
    }
}
0
额外

如果给定一个枚举器,并且需要在for-each循环中使用它,则可以使用以下内容来包装它:

static public class enumerationHelper
{
    public class enumeratorHolder
    {
        private T theEnumerator;
        public T GetEnumerator() { return theEnumerator; }
        public enumeratorHolder(T newEnumerator) { theEnumerator = newEnumerator;}
    }
    static enumeratorHolder toEnumerable(T theEnumerator) { return new enumeratorHolder(theEnumerator); }
    private class IEnumeratorHolder:IEnumerable
    {
        private IEnumerator theEnumerator;
        public IEnumerator GetEnumerator() { return theEnumerator; }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return theEnumerator; }
        public IEnumeratorHolder(IEnumerator newEnumerator) { theEnumerator = newEnumerator; }
    }
    static IEnumerable toEnumerable(IEnumerator theEnumerator) { return new IEnumeratorHolder(theEnumerator); }
}

The toEnumerable method will accept anything that or would regard an acceptable return type from GetEnumerator, and return something that can be used in foreach. If the parameter is an IEnumerator<> the response will be an IEnumerable, though calling GetEnumerator on it once will likely yield bad results.

0
额外

如果您返回IEnumerator,那么每次调用该方法时都会是不同的枚举器对象(就好像在每次迭代中重置枚举器一样)。如果您返回IEnumerable,则可以使用yield语句基于该方法枚举foreach。

0
额外

正如编译器告诉你的,你需要将你的返回类型改为IEnumerable。这就是yield return语法的工作原理。

0
额外
yield return 可以用于返回 IEnumerable IEnumerator </代码>。它只在 foreach 循环中才能使用 IEnumerator
额外 作者 Timwi,