Verwenden einer Visual C#-Klasse in einer foreach-Anweisung
In diesem Artikel wird veranschaulicht, wie Sie mithilfe der IEnumerable Schnittstellen IEnumerator eine Klasse 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 bietet iterative Funktionen für eine Auflistung, die intern für eine Klasse ist. IEnumerator erfordert, dass Sie drei Methoden implementieren:
Die
MoveNextMethode, die den Auflistungsindex um 1 erhöht und ein Bool zurückgibt, das angibt, ob das Ende der Auflistung erreicht wurde.Die
ResetMethode, die den Sammlungsindex auf den Anfangswert -1 zurücksetzt. Dadurch wird der Enumerator ungültig.Die
CurrentMethode, die das aktuelle Objekt unterpositionzurü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 welche Schnittstelle verwendet werden soll
Anfangs ist es möglicherweise verwirrend, diese Schnittstellen zu verwenden. Die IEnumerator Schnittstelle stellt eine Iteration über ein Sammlungsobjekt in einer Klasse bereit. Die IEnumerable Schnittstelle ermöglicht die Enumeration mithilfe einer foreach Schleife. Die GetEmunerator 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 implementieren IEnumerator, können Sie den Rückgabewert nicht aus der GetEnumerator Methode der IEnumerable Schnittstelle in die IEnumerator Schnittstelle umwandeln.
Zusammenfassend ist 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 Und-Schnittstellen 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 aufgrund der Implementierung dieser beiden Schnittstellen mithilfe eines foreach Konstrukts auflisten.
Führen Sie die folgenden Schritte aus, um ein neues Konsolenanwendungsprojekt in Visual C# zu erstellen:
- Starten Sie Microsoft Visual Studio .NET oder Visual Studio.
- Zeigen Sie im Menü Datei auf Neu, und klicken Sie dann auf Projekt.
- Unter Projekttypen klicken Sie auf Visual C#-Projekte. Klicken Sie dann unter Vorlagen auf die Option Konsolenanwendung.
- Geben Sie im Feld "Name " "ConsoleEnum" ein.
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(); } } }Klicken Sie im Menü Project auf "Klasse hinzufügen", und geben Sie dann das Auto in das Feld "Name" ein.
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 namespaceKlicken Sie im Menü Project auf "Klasse hinzufügen", um dem Projekt eine weitere Klasse hinzuzufügen, und geben Sie dann Autos in das Feld "Name" ein.
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];} } } }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 erklären. Um den Code robuster zu machen und sicherzustellen, dass der Code die aktuellen Richtlinien für bewährte Methoden verwendet, ändern Sie den Code wie folgt:
- Implementieren Sie
IEnumeratorsie in einer geschachtelten Klasse, damit Sie mehrere Enumeratoren erstellen können. - Bereitstellen der Ausnahmebehandlung für die
CurrentMethode vonIEnumerator. Wenn sich der Inhalt der Auflistung ändert, wird dieresetMethode aufgerufen. Daher wird der aktuelle Enumerator ungültig, und Sie erhalten eineIndexOutOfRangeExceptionAusnahme. Diese Ausnahme kann auch durch andere Umstände verursacht werden. Implementieren Sie also einenTry...CatchBlock zum Abfangen dieser Ausnahme und zum Auslösen einerInvalidOperationExceptionAusnahme.
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);
}
}
}