Compartilhar via


Como acessar uma classe de coleção com foreach (Guia de Programação em C#)

O exemplo de código a seguir ilustra como escrever uma classe de coleção não genérico que pode ser usada com foreach. O exemplo define uma classe de tokenizer de seqüência de caracteres.

Dica

Este exemplo representa a prática recomendada somente quando você não pode usar uma classe de coleção genérica.Para obter um exemplo de como implementar uma classe de coleção genérica de tipo seguro que ofereça suporte a IEnumerable, consulte Iteradores (C# e Visual Basic).

No exemplo, o código a seguir segmento usa a Tokens classe para quebrar a frase "Esta é uma frase de exemplo." em tokens usando ' ' e '-' como separadores. O código, em seguida, exibe esses tokens usando um foreach instrução.

Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});

// Display the tokens. 
foreach (string item in f)
{
    System.Console.WriteLine(item);
}

Exemplo

Internamente, o Tokens classe usa uma matriz para armazenar os tokens. Como as matrizes implementam IEnumerator e IEnumerable, o exemplo de código poderia ter usado a métodos de enumeração da matriz (GetEnumerator, MoveNext, Reset, e Current) em vez de defini-los na Tokens classe. As definições de método são incluídas no exemplo para esclarecer como são definidas e o que cada um oferece.

using System.Collections;

// Declare the Tokens class. The class implements the IEnumerable interface. 
public class Tokens : IEnumerable
{
    private string[] elements;

    Tokens(string source, char[] delimiters)
    {
        // The constructor parses the string argument into tokens.
        elements = source.Split(delimiters);
    }

    // The IEnumerable interface requires implementation of method GetEnumerator. 
    public IEnumerator GetEnumerator()
    {
        return new TokenEnumerator(this);
    }


    // Declare an inner class that implements the IEnumerator interface. 
    private class TokenEnumerator : IEnumerator
    {
        private int position = -1;
        private Tokens t;

        public TokenEnumerator(Tokens t)
        {
            this.t = t;
        }

        // The IEnumerator interface requires a MoveNext method. 
        public bool MoveNext()
        {
            if (position < t.elements.Length - 1)
            {
                position++;
                return true;
            }
            else
            {
                return false;
            }
        }

        // The IEnumerator interface requires a Reset method. 
        public void Reset()
        {
            position = -1;
        }

        // The IEnumerator interface requires a Current method. 
        public object Current
        {
            get
            {
                return t.elements[position];
            }
        }
    }


    // Test the Tokens class. 
    static void Main()
    {
        // Create a Tokens instance.
        Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});

        // Display the tokens. 
        foreach (string item in f)
        {
            System.Console.WriteLine(item);
        }
    }
}
/* Output:
    This
    is
    a
    sample
    sentence.  
*/

Em C#, não é necessário para implementar uma classe de coleção IEnumerable e IEnumerator para ser compatível com foreach. Se a classe tem o necessário GetEnumerator, MoveNext, Reset, e Current membros, ele funcionará com foreach. Omitir as interfaces tem a vantagem de permitindo que você defina um tipo de retorno para Current que é mais específico do que Object. Isso fornece segurança de tipos.

Por exemplo, altere as seguintes linhas no exemplo anterior.

// Change the Tokens class so that it no longer implements IEnumerable.
public class Tokens
{
    // . . .

    // Change the return type for the GetEnumerator method.
    public TokenEnumerator GetEnumerator()
    {   }

    // Change TokenEnumerator so that it no longer implements IEnumerator.
    public class TokenEnumerator
    {
        // . . .

        // Change the return type of method Current to string.
        public string Current
        {   }
    }
 }

Porque Current retorna uma seqüência de caracteres, o compilador pode detectar quando um tipo incompatível é usado em um foreach instrução, como mostrado no código a seguir.

// Error: Cannot convert type string to int.
foreach (int item in f)  

A desvantagem de omissão IEnumerable e IEnumerator é que a classe de coleção não é interoperável com o foreach declarações ou instruções equivalentes, de outros idiomas de runtime de linguagem comum.

Consulte também

Referência

Matrizes (Guia de Programação em C#)

System.Collections.Generic

Conceitos

Guia de Programação em C#

Outros recursos

Referência de C#

Coleções (C# e Visual Basic)