Posso ter um método retornar IEnumerator <T> e usá-lo em um loop foreach?

votos
16

Eu preciso definir a altura de cada caixa de texto no meu formulário, alguns dos quais são aninhados dentro de outros controles. Eu pensei que eu poderia fazer algo parecido com isto:

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

Usá-lo como este:

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

Mas é claro que o compilador cospe seu manequim, porque foreach espera um IEnumerable em vez de um IEnumerator .

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

Publicado 06/08/2008 em 13:17
fonte usuário
Em outras línguas...                            


5 respostas

votos
13

Como o compilador está lhe dizendo, você precisa mudar o seu tipo de retorno para IEnumerable. Isso é como a sintaxe rendimento retorno funciona.

Respondeu 06/08/2008 em 13:19
fonte usuário

votos
9

Só para esclarecer

private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)

Muda para

private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)

Isso deve ser tudo :-)

Respondeu 09/08/2008 em 00:34
fonte usuário

votos
3

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

Respondeu 06/08/2008 em 14:04
fonte usuário

votos
1
// 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;
    }
}
Respondeu 06/08/2008 em 13:32
fonte usuário

votos
0

Se você é dado um enumerador, e precisa usá-lo em um for-each loop, você poderia usar o seguinte para envolvê-la:

enumerationHelper classe public static
{
    classe pública enumeratorHolder <T>
    {
        private T theEnumerator;
        público T GetEnumerator () {return theEnumerator; }
        enumeratorHolder pública (T newEnumerator) {theEnumerator = newEnumerator;}
    }
    estática enumeratorHolder <T> toEnumerable <T> (T theEnumerator) {return new enumeratorHolder <T> (theEnumerator); }
    classe privada IEnumeratorHolder <T>: IEnumerable <T>
    {
        IEnumerator private <T> theEnumerator;
        pública IEnumerator <T> GetEnumerator () {return theEnumerator; }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () {return theEnumerator; }
        pública IEnumeratorHolder (IEnumerator <T> newEnumerator) {theEnumerator = newEnumerator; }
    }
    estática IEnumerable <T> toEnumerable <T> (IEnumerator <T> theEnumerator) {return new IEnumeratorHolder <T> (theEnumerator); }
}

O toEnumerablemétodo vai aceitar qualquer coisa que ou consideraria um tipo de retorno aceitável a partir GetEnumeratore retornar algo que pode ser usado em foreach. Se o parâmetro é um IEnumerator<>a resposta será um IEnumerable<T>, embora chamando GetEnumeratornele uma vez, provavelmente, produzir resultados ruins.

Respondeu 14/07/2011 em 20:09
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more