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 beiposition
zurü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 IEnumerable
von 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 foreach
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
Schnittstellen und IEnumerable
in einer Klasse mit dem Namen cars
verwendet. 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.
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 den Namen 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ü Projekt auf Klasse hinzufügen, und geben Sie dann car 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 namespace
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.
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 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 bereitIEnumerator
. Wenn sich der Inhalt der Auflistung ändert, wird diereset
-Methode aufgerufen. Dadurch wird der aktuelle Enumerator ungültig, und Sie erhalten eineIndexOutOfRangeException
Ausnahme. Diese Ausnahme kann auch durch andere Umstände verursacht werden. Implementieren Sie daher einenTry...Catch
-Block, um diese Ausnahme abzufangen und eine Ausnahme auszulösenInvalidOperationException
.
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);
}
}
}
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für