Freigeben über


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

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

Originalproduktversion: 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 Sammlung bereit, die für eine Klasse intern ist. IEnumerator erfordert, dass Sie drei Methoden implementieren:

  • Die MoveNext Methode, die den Auflistungsindex um 1 erhöht und einen Bool zurückgibt, der angibt, ob das Ende der Auflistung erreicht wurde.

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

  • Die Current Methode, die das aktuelle Objekt angibt.position

    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 soll welche Schnittstelle verwendet werden?

Zunächst kann es verwirrend sein, diese Schnittstellen zu verwenden. Die IEnumerator Schnittstelle stellt eine Iteration über ein Auflistungstypobjekt in einer Klasse bereit. Die IEnumerable Schnittstelle ermöglicht die Aufzählung mithilfe einer foreach Schleife. GetEnumerator Die Methode der IEnumerable Schnittstelle gibt jedoch eine IEnumerator Schnittstelle zurück. Um dies zu implementieren IEnumerable, müssen Sie auch implementieren IEnumerator. Wenn Sie dies nicht implementierenIEnumerator, können Sie den Rückgabewert nicht aus der Methode IEnumerable IEnumerator der GetEnumerator Schnittstelle umwandeln.

Zusammenfassend erfordert die Verwendung, IEnumerable dass die Klasse implementiert IEnumeratorwird. Wenn Sie Unterstützung für foreachbeide Schnittstellen bereitstellen 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 Und IEnumerable Schnittstellen in einer Klasse mit dem Namen carsverwendet. Die cars Klasse verfügt über ein internes Array von car Objekten. Clientanwendungen können über dieses interne Array mithilfe eines foreach Konstrukts aufzählen, da diese beiden Schnittstellen umgesetzt werden.

  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. Klicken Sie unter Projekttypen auf Visual C#-Projekte, und klicken Sie dann unter "Vorlagen" auf "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 im Feld "Name" den Wagen 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 im Feld "Name" Autos 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 wird 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 Richtlinien für bewährte Methoden verwendet, ändern Sie den Code wie folgt:

  • Implementieren Sie IEnumerator in einer geschachtelten Klasse, sodass Sie mehrere Enumerationen erstellen können.
  • Bereitstellen der Ausnahmebehandlung für die Current Methode von IEnumerator. Wenn sich der Inhalt der Auflistung ändert, wird die reset Methode aufgerufen. Daher wird der aktuelle Enumerator ungültig, und Sie erhalten eine IndexOutOfRangeException Ausnahme. Andere Umstände können auch zu dieser Ausnahme führen. Implementieren Sie also einen Try...Catch Block, um diese Ausnahme abzufangen und eine InvalidOperationException Ausnahme auszulösen.
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);
      }
    }
}