Verwenden einer Visual C#-Klasse in einer foreach-Anweisung

In diesem Artikel wird veranschaulicht, wie Sie die IEnumerable Schnittstellen und IEnumerator verwenden, um eine Klasse zu erstellen, die Sie in einer foreach -Anweisung verwenden können.

Ursprüngliche Produktversion: Visual Studio
Ursprüngliche KB-Nummer: 322022

IEnumerator-Schnittstelle

IEnumerable und IEnumerator werden häufig zusammen verwendet. Obwohl diese Schnittstellen ähnlich sind (und ähnliche Namen haben), haben sie unterschiedliche Zwecke.

Die IEnumerator -Schnittstelle stellt iterative Funktionen für eine Auflistung bereit, die in einer Klasse intern ist. IEnumerator erfordert, dass Sie drei Methoden implementieren:

  • Die MoveNext -Methode, die den Auflistungsindex um 1 inkrementiert und ein Bool zurückgibt, das angibt, ob das Ende der Auflistung erreicht wurde.

  • Die Reset -Methode, die den Auflistungsindex auf den Anfangswert -1 zurücksetzt. Dadurch wird der Enumerator ungültig.

  • Die Current -Methode, die das aktuelle -Objekt bei positionzurückgibt.

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

IEnumerable-Schnittstelle

Die IEnumerable -Schnittstelle bietet Unterstützung für die foreach Iteration. IEnumerable erfordert, dass Sie die GetEnumerator -Methode implementieren.

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

Wann sollte welche Schnittstelle verwendet werden?

Zunächst kann es verwirrend sein, diese Schnittstellen zu verwenden. Die IEnumerator -Schnittstelle stellt Iterationen über ein Auflistungsobjekt in einer Klasse bereit. Die IEnumerable -Schnittstelle ermöglicht die Enumeration mithilfe einer foreach -Schleife. Die GetEnumerator -Methode der IEnumerable -Schnittstelle gibt jedoch eine IEnumerator Schnittstelle zurück. Zum Implementieren IEnumerablevon müssen Sie also auch implementieren IEnumerator. Wenn Sie nicht implementieren IEnumerator, können Sie den Rückgabewert nicht von der GetEnumerator -Methode in IEnumerable die IEnumerator -Schnittstelle umwandeln.

Zusammenfassend ist es für die Verwendung von IEnumerable erforderlich, dass die -Klasse implementiert IEnumerator. Wenn Sie Unterstützung für foreachbereitstellen möchten, implementieren Sie beide Schnittstellen.

Schritt-für-Schritt-Beispiel

Im folgenden Beispiel wird die Verwendung dieser Schnittstellen veranschaulicht. In diesem Beispiel werden die IEnumerator Schnittstellen und IEnumerable in einer Klasse mit dem Namen carsverwendet. Die cars -Klasse verfügt über ein internes Array von car -Objekten. Clientanwendungen können dieses interne Array mithilfe eines foreach -Konstrukts auflisten, da diese beiden Schnittstellen implementiert sind.

  1. Führen Sie die folgenden Schritte aus, um ein neues Konsolenanwendungsprojekt in Visual C# zu erstellen:

    1. Starten Sie Microsoft Visual Studio .NET oder Visual Studio.
    2. Zeigen Sie im Menü Datei auf Neu, und klicken Sie dann auf Projekt.
    3. Unter Projekttypen klicken Sie auf Visual C#-Projekte. Klicken Sie dann unter Vorlagen auf die Option Konsolenanwendung.
    4. Geben Sie im Feld Name den Namen ConsoleEnum ein.
  2. Benennen Sie Class1.cs in host.cs um, und ersetzen Sie dann den Code in host.cs durch den folgenden Code:

    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. Klicken Sie im Menü Projekt auf Klasse hinzufügen, und geben Sie dann car in das Feld Name ein.

  4. Ersetzen Sie den Code in car.cs durch den folgenden Code:

    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. Klicken Sie im Menü Projekt auf Klasse hinzufügen , um dem Projekt eine weitere Klasse hinzuzufügen, und geben Sie dann autos in das Feld Name ein.

  6. Ersetzen Sie den Code in cars.cs durch den folgenden Code:

    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. Führen Sie das Projekt aus.

Die folgende Ausgabe wird im Konsolenfenster angezeigt:

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

Bewährte Methoden

Das Beispiel in diesem Artikel ist so einfach wie möglich gehalten, um die Verwendung dieser Schnittstellen besser zu erläutern. Um den Code robuster zu gestalten und sicherzustellen, dass der Code die aktuellen Best Practices-Richtlinien verwendet, ändern Sie den Code wie folgt:

  • Implementieren Sie IEnumerator in einer geschachtelten Klasse, sodass Sie mehrere Enumeratoren erstellen können.
  • Stellen Sie die Ausnahmebehandlung für die Current -Methode von bereit IEnumerator. Wenn sich der Inhalt der Auflistung ändert, wird die reset -Methode aufgerufen. Dadurch wird der aktuelle Enumerator ungültig, und Sie erhalten eine IndexOutOfRangeException Ausnahme. Diese Ausnahme kann auch durch andere Umstände verursacht werden. Implementieren Sie daher einen Try...Catch -Block, um diese Ausnahme abzufangen und eine Ausnahme auszulösen InvalidOperationException .
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);
      }
    }
}