Thursday, February 3, 2011

C#: Can I have a method return IEnumerator<T> and use it in a foreach loop?

Howdy,

I need to set the height of every textbox on my form, some of which are nested within other controls. I thought I could do something like this:

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;
}
}
}

Using it like this:

foreach(TextBox textBox in FindTextBoxes(this))
{
textBox.Height = height;
}

But of course the compiler spits its dummy, because foreach expects an IEnumerable rather than an IEnumerator.

Is there a way to do this without having to create a separate class with a GetEnumerator() method?

Am I mad?

Anthony

  • As the compiler is telling you, you need to change your return type to IEnumerable. That is how the yield return syntax works.

    Timwi : `yield return` can be used with methods that return *either* `IEnumerable` *or* `IEnumerator`. It’s only in the `foreach` loop where `IEnumerator` can’t be used.
    From Ch00k
  • // 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;
    }
    }
  • I can't believe it was that simple, thanks.

    Timwi : Please delete this answer because it is not an answer. Thanks!
  • If you return IEnumerator, it will be a different enumerator object each time call that method (acting as though you reset the enumerator on each iteration). If you return IEnumerable then a foreach can enumerate based on the method with the yield statement.

  • Just to clarify

    private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)

    Changes to

    private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)

    That should be all :-)

0 comments:

Post a Comment