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

Translate

Ich muss die Höhe jedes Textfelds in meinem Formular festlegen, von denen einige in anderen Steuerelementen verschachtelt sind. 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;
        }
    }
}

Verwenden Sie es so:

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

Aber natürlich spuckt der Compiler seinen Dummy aus, weilfür jedenerwartet eineIEnumerableeher als einIEnumerator.

Gibt es eine Möglichkeit, dies zu tun, ohne eine separate Klasse mit a erstellen zu müssen?GetEnumerator ()Methode?

This question and all comments follow the "Attribution Required."

Alle Antworten

Translate

Wie der Compiler Ihnen mitteilt, müssen Sie Ihren Rückgabetyp in IEnumerable ändern. So funktioniert die Yield-Return-Syntax.

Quelle
Translate

Nur um klarzustellen

private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)

Änderungen an

private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)

Das sollte alles sein :-)

Quelle
Translate

Wenn Sie IEnumerator zurückgeben, handelt es sich bei jedem Aufruf dieser Methode um ein anderes Enumerator-Objekt (so, als würden Sie den Enumerator bei jeder Iteration zurücksetzen). Wenn Sie IEnumerable zurückgeben, kann ein foreach basierend auf der Methode mit der Yield-Anweisung auflisten.

Quelle
Translate
// 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;
    }
}
Quelle
Translate

Wenn Sie einen Enumerator erhalten und ihn in einer for-each-Schleife verwenden müssen, können Sie ihn wie folgt umbrechen:

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

DastoEnumerableMethode akzeptiert alles, wasoderwürde einen akzeptablen Rückgabetyp von betrachtenGetEnumeratorund geben Sie etwas zurück, das in verwendet werden kannforeach. Wenn der Parameter ein istIEnumerator<>Die Antwort wird eine seinIEnumerable<T>, obwohl ich anrufeGetEnumeratoreinmal darauf wird wahrscheinlich schlechte Ergebnisse liefern.

Quelle