Kann ich eine Methode haben, die IEnumerator <T> zurückgibt und in einer foreach-Schleife verwendet?

  • Ich muss die Höhe jedes Textfelds in meinem Formular festlegen. Einige davon sind in anderen Steuerelementen verschachtelt. Ich dachte, ich könnte so etwas tun:

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

    So wird es verwendet:

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

    Natürlich spuckt der Compiler seinen Dummy aus, denn foreach erwartet eine IEnumerable statt eines IEnumerator .

    Gibt es eine Möglichkeit, dies zu tun, ohne eine separate Klasse mit einem GetEnumerator () Methode?

    22 October 2015
    Vitor Guerreirolittlecharva
5 answers
  • Da der Compiler Ihnen mitteilt, müssen Sie Ihren Rückgabetyp in IEnumerable ändern. So funktioniert die Yield Return-Syntax.

    06 August 2008
    David Wengier
  • Nur zur Klarstellung

     private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
     

    Änderungen an

     private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)
     

    Das sollte alles sein: -)

    09 August 2008
    Orion Edwards
  • Wenn Sie IEnumerator zurückgeben, handelt es sich bei jedem Aufruf dieser Methode um ein anderes Enumerator-Objekt (das bei jeder Iteration den Enumerator zurücksetzt). Wenn Sie IEnumerable zurückgeben, kann ein Foreach basierend auf der Methode mit der Yield-Anweisung auflisten.

    06 August 2008
    Joseph Daigle
  •  // 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;
        }
    }
     
    31 August 2015
    AbhishekAdam Wright
  • Wenn Sie einen Enumerator erhalten und ihn in einer for-each-Schleife verwenden müssen, können Sie ihn folgendermaßen umschließen:

     statische öffentliche Klasse enumerationHelper 
     {
     public class enumeratorHolder & lt; T & gt; 
     {
     private T theEnumerator; 
     public T GetEnumerator () {return theEnumerator; } 
     public enumeratorHolder (T newEnumerator) {theEnumerator = neuerEnumerator;} 
    } 
     statischer EnumeratorHolder & lt; T & gt; toEnumerable & lt; T & gt; (T theEnumerator) {return new enumeratorHolder & lt; T & gt; (theEnumerator); } 
     private Klasse IEnumeratorHolder & lt; T & gt;: IEnumerable & lt; T & gt; 
     {
     private IEnumerator & lt; T & gt; theEnumerator; 
     public IEnumerator & lt; T & gt; GetEnumerator () {return theEnumerator; } 
     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () {return theEnumerator; } 
     public IEnumeratorHolder (IEnumerator & lt; T & gt; newEnumerator) {theEnumerator = newEnumerator; } 
    } 
     statisch IEnumerable & lt; T & gt; toEnumerable & lt; T & gt; (IEnumerator & lt; T & gt; theEnumerator) {Rückgabe neuer IEnumeratorHolder & lt; T & gt; (theEnumerator); } 
    } 
     

    Die Methode toEnumerable akzeptiert alles, was oder würde einen akzeptablen Rückgabetyp von GetEnumerator betrachten und etwas zurückgeben, das in foreach verwendet werden kann. Wenn der Parameter ein IEnumerator<> ist, wird die Antwort ein IEnumerable<T> sein, obwohl ein einmaliger Aufruf von GetEnumerator wahrscheinlich zu schlechten Ergebnissen führt.

    31 August 2015
    AbhishekAdam Wright