Partager via


Comment : accéder à une classe de collection à l'aide de foreach (Guide de programmation C#)

L'exemple de code suivant explique comment écrire une classe de collection non générique qui peut être utilisée avec foreach. L'exemple définit une classe de générateur de jetons de chaîne.

Notes

Cet exemple représente uniquement la méthode recommandée dans les cas où vous ne pouvez pas utiliser de classe de collection générique. Pour obtenir un exemple d'implémentation d'une classe de collection générique de type sécurisé qui prend en charge IEnumerable<T>, consultez Comment : créer un bloc itérateur pour une liste générique (Guide de programmation C#).

Dans l'exemple, le segment de code suivant utilise la classe Tokens utilise la classe pour décomposer la phrase « ceci est un exemple de phrase. » en jetons à l'aide des séparateurs ' ' et '-'. Le code affiche ensuite ces jetons en utilisant une instruction foreach.

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

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

Exemple

En interne, la classe Tokens utilise un tableau pour stocker les jetons. Étant donné que les tableaux implémentent IEnumerator et IEnumerable, l'exemple de code aurait pu utiliser les méthodes d'énumération du tableau (GetEnumerator, MoveNext, Reset et Current) au lieu de les définir dans la classe Tokens. Les définitions de méthode sont incluses dans l'exemple pour clarifier la façon dont elles sont définies et le rôle de chacune d'entre-elles.

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#, il n'est pas nécessaire qu'une classe de collection implémente IEnumerable et IEnumerator pour être compatible avec foreach. Si la classe possède les membres GetEnumerator, MoveNext, Reset et Current requis, cela fonctionnera avec foreach. L'omission des interfaces est intéressante dans la mesure où elle vous permet de définir un type de retour pour Current plus spécifique que Object et d'assurer une sécurité de type. Cela garantit la sécurité de type.

Par exemple, modifiez les lignes suivantes dans l'exemple précédent.

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

Étant donné que Current retourne une chaîne, le compilateur peut détecter qu'un type incompatible est utilisé dans une instruction foreach, comme indiqué dans le code suivant.

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

L'omission de IEnumerable et IEnumerator présente cependant un inconvénient : la classe de collection ne peut plus fonctionner avec les instructions foreach, ou leurs équivalents, des autres langages compatibles avec le CLR (Common Language Runtime).

Voir aussi

Référence

Tableaux (guide de programmation C#)

Classes de collection (Guide de programmation C#)

System.Collections.Generic

Concepts

Guide de programmation C#

Autres ressources

Référence C#

Historique des modifications

Date

Historique

Motif

Mars 2011

Modifié pour améliorer la clarté.

Améliorations apportées aux informations.