Pergunta

Preciso definir a altura de cada caixa de texto no meu formulário, algumas das quais estão aninhadas em outros controles.Eu pensei que poderia fazer algo assim:

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

Usando assim:

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

Mas é claro que o compilador cospe seu boneco, porque para cada espera um IEnumerable em vez de um IEnumerador.

Existe uma maneira de fazer isso sem ter que criar uma classe separada com um GetEnumerator() método?

Foi útil?

Solução

Como o compilador está informando, você precisa alterar seu tipo de retorno para IEnumerable.É assim que funciona a sintaxe de retorno de rendimento.

Outras dicas

Só para esclarecer

private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)

Muda para

private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)

Isso deve ser tudo :-)

Se você retornar IEnumerator, será um objeto enumerador diferente cada vez que chamar esse método (agindo como se você redefinisse o enumerador em cada iteração).Se você retornar IEnumerable, um foreach poderá enumerar com base no método com a instrução de rendimento.

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

Se você receber um enumerador e precisar usá-lo em um loop for-each, poderá usar o seguinte para envolvê-lo:

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

O toEnumerable método aceitará qualquer coisa que ou consideraria um tipo de retorno aceitável de GetEnumerator, e retorne algo que possa ser usado em foreach.Se o parâmetro for um IEnumerator<> a resposta será uma IEnumerable<T>, embora ligando GetEnumerator fazer isso uma vez provavelmente produzirá resultados ruins.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top