Share via


Cómo: Obtener acceso a una clase de colección mediante Foreach (Guía de programación de C#)

En el ejemplo de código siguiente se muestra cómo se escribe una clase Collection no genérica que se puede usar con la instrucción foreach.En el ejemplo se define una clase de tokenización de cadenas.

[!NOTA]

Este ejemplo representa la práctica recomendada sólo cuando no se puede utilizar una clase de colección genérica.Para obtener un ejemplo de cómo se implementa una clase Collection genérica con seguridad de tipos que admita IEnumerable<T>, vea Iteradores (C# y Visual Basic).

En el ejemplo, el siguiente segmento de código usa la clase Tokens para dividir la frase "This is a sample sentence." en tokens usando ' ' y '-' como separadores.A continuación, el código muestra esos tokens mediante una instrucción foreach.

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

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

Ejemplo

Internamente, la clase Tokens usa una matriz para almacenar los tokens.Como las matrices implementan las interfaces IEnumerator e IEnumerable, el ejemplo de código podría haber usado los métodos de enumeración de la matriz (GetEnumerator, MoveNext, Reset y Current) en lugar de definirlos en la clase Tokens.Las definiciones de los métodos se incluyen en el ejemplo para clarificar cómo están definidos y qué hace cada uno.

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.  
*/

En C#, no es necesario que una clase Collection implemente IEnumerable y IEnumerator para que sea compatible con foreach.Si la clase tiene los miembros GetEnumerator, MoveNext, Resety Current necesarios, funcionará con foreach.Omitir las interfaces tiene la ventaja de que permite definir un tipo de valor devuelto de Current que es más específico que Object.Esto proporciona seguridad de tipos.

Por ejemplo, cambie las siguientes líneas del ejemplo 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
        {   }
    }
 }

Dado que Current devuelve una cadena, el compilador puede detectar cuándo se usa un tipo incompatible en una instrucción foreach, tal y como se muestra en el código siguiente.

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

El inconveniente de omitir IEnumerable e IEnumerator es que la clase Collection ya no puede interactuar con las instrucciones foreach (o equivalentes) de otros lenguajes compatibles con Common Language Runtime.

Vea también

Referencia

Matrices (Guía de programación de C#)

System.Collections.Generic

Conceptos

Guía de programación de C#

Otros recursos

Referencia de C#

Colecciones (C# y Visual Basic)