Lire en anglais

Partager via


Rendre une classe Visual C# utilisable dans une instruction foreach

Cet article montre comment utiliser les interfaces et les IEnumerable IEnumerator interfaces pour créer une classe que vous pouvez utiliser dans une foreach instruction.

Version du produit d’origine : Visual Studio
Numéro de base de connaissances d’origine : 322022

Interface IEnumerator

IEnumerable et IEnumerator sont fréquemment utilisés ensemble. Bien que ces interfaces soient similaires (et ont des noms similaires), elles ont des objectifs différents.

L’interface IEnumerator fournit une fonctionnalité itérative pour une collection interne à une classe. IEnumerator exige que vous implémentez trois méthodes :

  • La MoveNext méthode, qui incrémente l’index de collection de 1 et retourne un bool qui indique si la fin de la collection a été atteinte.

  • Méthode Reset , qui réinitialise l’index de collection à sa valeur initiale de -1. Cela invalide l’énumérateur.

  • Méthode Current , qui retourne l’objet actuel à position.

    C#
    public bool MoveNext()
    {
        position++;
        return (position < carlist.Length);
    }
    public void Reset()
    {
        position = -1;
    }
    public object Current
    {
        get { return carlist[position];}
    }
    

Interface IEnumerable

L’interface IEnumerable prend en charge l’itération foreach . IEnumerable exige que vous implémentez la GetEnumerator méthode.

C#
public IEnumerator GetEnumerator()
{
    return (IEnumerator)this;
}

Quand utiliser l’interface

Au départ, il peut être déroutant d’utiliser ces interfaces. L’interface IEnumerator fournit une itération sur un objet de type collection dans une classe. L’interface IEnumerable autorise l’énumération à l’aide d’une foreach boucle. Toutefois, la GetEnumerator méthode de l’interface IEnumerable retourne une IEnumerator interface. Ainsi, pour implémenter IEnumerable, vous devez également implémenter IEnumerator. Si vous n’implémentez IEnumeratorpas, vous ne pouvez pas convertir la valeur de retour de la GetEnumerator méthode de IEnumerable l’interface IEnumerator .

En résumé, l’utilisation de IEnumerable nécessite que la classe implémente IEnumerator. Si vous souhaitez fournir une prise en charge, foreachimplémentez les deux interfaces.

Exemple étape par étape

L’exemple suivant montre comment utiliser ces interfaces. Dans cet exemple, les interfaces et IEnumerable les IEnumerator interfaces sont utilisées dans une classe nommée cars. La cars classe a un tableau interne d’objets car . Les applications clientes peuvent énumérer ce tableau interne à l’aide d’une foreach construction en raison de l’implémentation de ces deux interfaces.

  1. Procédez comme suit pour créer un projet d’application console dans Visual C# :

    1. Démarrez Microsoft Visual Studio .NET ou Visual Studio.
    2. Dans le menu Fichier , pointez sur Nouveau, puis cliquez sur Projet.
    3. Cliquez sur Projets Visual C# sous Types de projets, puis sur Application console sous Modèles.
    4. Dans la zone Nom , tapez ConsoleEnum.
  2. Renommez Class1.cs en host.cs, puis remplacez le code dans host.cs par le code suivant :

    C#
    using System;
    namespace ConsoleEnum
    {
       class host
       {
           [STAThread]
           static void Main(string[] args)
           {
               cars C = new cars();
               Console.WriteLine("\nInternal Collection (Unsorted - IEnumerable,Enumerator)\n");
               foreach(car c in C)
               Console.WriteLine(c.Make + "\t\t" + c.Year);
               Console.ReadLine();
           }
       }
    }
    
  3. Dans le menu Projet , cliquez sur Ajouter une classe, puis tapez la voiture dans la zone Nom .

  4. Remplacez le code dans car.cs par le code suivant :

    C#
    using System;
    using System.Collections;
    namespace ConsoleEnum
    {
       public class car
       {
           private int year;
           private string make;
           public car(string Make,int Year)
           {
               make=Make;
               year=Year;
           }
           public int Year
           {
               get  {return year;}
               set {year=value;}
           }
           public string Make
           {
               get {return make;}
               set {make=value;}
           }
       }//end class
    }//end namespace
    
  5. Dans le menu Projet , cliquez sur Ajouter une classe pour ajouter une autre classe au projet, puis tapez des voitures dans la zone Nom .

  6. Remplacez le code dans cars.cs par le code suivant :

    C#
    using System;
    using System.Collections;
    namespace ConsoleEnum
    {
        public class cars : IEnumerator,IEnumerable
        {
           private car[] carlist;
           int position = -1;
           //Create internal array in constructor.
           public cars()
           {
               carlist= new car[6]
               {
                   new car("Ford",1992),
                   new car("Fiat",1988),
                   new car("Buick",1932),
                   new car("Ford",1932),
                   new car("Dodge",1999),
                   new car("Honda",1977)
               };
           }
           //IEnumerator and IEnumerable require these methods.
           public IEnumerator GetEnumerator()
           {
               return (IEnumerator)this;
           }
           //IEnumerator
           public bool MoveNext()
           {
               position++;
               return (position < carlist.Length);
           }
           //IEnumerable
           public void Reset()
           {
               position = -1;
           }
           //IEnumerable
           public object Current
           {
               get { return carlist[position];}
           }
        }
      }
    
  7. Exécutez le projet .

La sortie suivante s’affiche dans la fenêtre console :

Console
Ford            1992
Fiat            1988
Buick           1932
Ford            1932
Dodge           1999
Honda           1977

Bonnes pratiques

L’exemple de cet article est conservé aussi simple que possible pour mieux expliquer l’utilisation de ces interfaces. Pour rendre le code plus robuste et s’assurer que le code utilise les recommandations actuelles en matière de bonnes pratiques, modifiez le code comme suit :

  • Implémentez IEnumerator dans une classe imbriquée afin de pouvoir créer plusieurs énumérateurs.
  • Fournir la gestion des exceptions pour la Current méthode de IEnumerator. Si le contenu de la collection change, la reset méthode est appelée. Par conséquent, l’énumérateur actuel est invalidé et vous recevez une IndexOutOfRangeException exception. D’autres circonstances peuvent également provoquer cette exception. Implémentez donc un Try...Catch bloc pour intercepter cette exception et déclencher une InvalidOperationException exception.
C#
using System;
using System.Collections;
namespace ConsoleEnum
{
    public class cars : IEnumerable
    {
        private car[] carlist;
  
        //Create internal array in constructor.
        public cars()
        {
            carlist= new car[6]
            {
                new car("Ford",1992),
                new car("Fiat",1988),
                new car("Buick",1932),
                new car("Ford",1932),
                new car("Dodge",1999),
                new car("Honda",1977)
            };
        }
        //private enumerator class
        private class  MyEnumerator:IEnumerator
        {
            public car[] carlist;
            int position = -1;

            //constructor
            public MyEnumerator(car[] list)
            {
                carlist=list;
            }
            private IEnumerator getEnumerator()
            {
                return (IEnumerator)this;
            }
            //IEnumerator
            public bool MoveNext()
            {
                position++;
                return (position < carlist.Length);
            }
            //IEnumerator
            public void Reset()
            {
                position = -1;
            }
            //IEnumerator
            public object Current
            {
                get
                {
                    try
                    {
                        return carlist[position];
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }
        }  //end nested class
      public IEnumerator GetEnumerator()
      {
          return new MyEnumerator(carlist);
      }
    }
}