Procedura: accedere a una classe di insiemi con foreach (Guida per programmatori C#)

Nell'esempio di codice seguente viene illustrato come scrivere una classe di insieme non generica utilizzabile con foreach. Nell'esempio viene definita una classe tokenizer di stringa.

Nota

La procedura riportata in questo esempio è consigliata solo quando non è possibile utilizzare una classe Collection generica. Per un esempio di come implementare una classe di insieme generica indipendente dai tipi che supporta IEnumerable<T>, vedere Procedura: creare un blocco iteratore per un elenco generico (Guida per programmatori C#).

Nell'esempio il segmento di codice seguente utilizza la classe Tokens per suddividere la frase "This is a sample sentence." in token utilizzando ' ' e '-' come separatori. Il codice consente quindi di visualizzare tali token utilizzando un'istruzione foreach.

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

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

Esempio

Internamente, la classe Tokens utilizza una matrice per archiviare i token. Poiché le matrici implementano IEnumerator e IEnumerable, l'esempio di codice avrebbe potuto utilizzare i metodi di enumerazione della matrice (GetEnumerator, MoveNext, Reset e Current) anziché definirli nella classe Tokens. Le definizioni dei metodi sono incluse nell'esempio per chiarire come vengono definiti i metodi e lo scopo di ognuno di essi.

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

In C# non è necessario che una classe di insieme implementi IEnumerable e IEnumerator per essere compatibile con foreach. Se la classe dispone dei membri GetEnumerator, MoveNext, Reset e Current necessari, funzionerà con foreach. L'omissione delle interfacce consente di definire come tipo restituito da Current un tipo più specifico di Object. In questo modo viene garantita l'indipendenza dai tipi.

Modificare ad esempio le righe seguenti dell'esempio precedente.

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

Poiché Current restituisce una stringa, il compilatore è in grado di rilevare l'eventuale utilizzo di un tipo non compatibile in un'istruzione foreach, come illustrato nel codice seguente.

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

L'omissione di IEnumerable e IEnumerator impedisce tuttavia l'interoperabilità della classe di insieme con le istruzioni foreach o con istruzioni equivalenti di altri linguaggi compatibili con Common Language Runtime.

Vedere anche

Riferimenti

Matrici (Guida per programmatori C#)

Classi di insiemi (Guida per programmatori C#)

System.Collections.Generic

Concetti

Guida per programmatori C#

Altre risorse

Riferimenti per C#

Cronologia delle modifiche

Data

Cronologia

Motivo

Marzo 2011

Revisione del contenuto per renderlo più chiaro.

Miglioramento delle informazioni.