首页 / 知识

关于c#:我可以使用返回IEnumerator < T >的方法并将其用于foreach循环中吗?

2023-04-11 17:49:00

关于c#:我可以使用返回IEnumerator < T >的方法并将其用于foreach循环中吗?

Can I have a method returning IEnumerator and use it in a foreach loop?

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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;
        }
    }
}

像这样使用它:

1
2
3
4
foreach(TextBox textBox in FindTextBoxes(this))
{
    textBox.Height = height;
}

但是,当然编译器会吐出它的虚拟对象,因为foreach期望使用IEnumerable而不是IEnumerator。

有没有一种方法可以不必使用GetEnumerator()方法创建单独的类?


正如编译器告诉您的那样,您需要将返回类型更改为IEnumerable。 这就是yield return语法的工作方式。


只是为了澄清

1
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)

更改为

1
private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)

那应该是全部:-)


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 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;
    }
}

如果为您提供了枚举器,并且需要在for-each循环中使用它,则可以使用以下代码对其进行包装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static public class enumerationHelper
{
    public class enumeratorHolder< T >
    {
        private T theEnumerator;
        public T GetEnumerator() { return theEnumerator; }
        public enumeratorHolder(T newEnumerator) { theEnumerator = newEnumerator;}
    }
    static enumeratorHolder< T > toEnumerable< T >(T theEnumerator) { return new enumeratorHolder< T >(theEnumerator); }
    private class IEnumeratorHolder< T >:IEnumerable< T >
    {
        private IEnumerator< T > theEnumerator;
        public IEnumerator< T > GetEnumerator() { return theEnumerator; }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return theEnumerator; }
        public IEnumeratorHolder(IEnumerator< T > newEnumerator) { theEnumerator = newEnumerator; }
    }
    static IEnumerable< T > toEnumerable< T >(IEnumerator< T > theEnumerator) { return new IEnumeratorHolder< T >(theEnumerator); }
}

toEnumerable方法将接受c#或vb认为是GetEnumerator可接受的返回类型的任何内容,并返回可以在foreach中使用的内容。 如果参数是IEnumerator<>,则响应将是IEnumerable< T >,尽管对其一次调用GetEnumerator可能会产生不好的结果。


用于方法循环文本框

最新内容

相关内容

热门文章

推荐文章

标签云

猜你喜欢