Czy ktoś może mi wyjaśnić IEnumerable i IEnumerator?
na przykład, kiedy użyć go za foreach? Jaka jest różnica między IEnumerable i IEnumerator? Dlaczego musimy go używać?
Czy ktoś może mi wyjaśnić IEnumerable i IEnumerator?
na przykład, kiedy użyć go za foreach? Jaka jest różnica między IEnumerable i IEnumerator? Dlaczego musimy go używać?
Odpowiedzi:
na przykład, kiedy użyć go za foreach?
Nie używasz IEnumerable
„ponad” foreach
. Wykonawcze IEnumerable
sprawia, że korzystanie foreach
to możliwe .
Kiedy piszesz kod taki jak:
foreach (Foo bar in baz)
{
...
}
jest funkcjonalnie równoważny z pisaniem:
IEnumerator bat = baz.GetEnumerator();
while (bat.MoveNext())
{
bar = (Foo)bat.Current
...
}
Przez „funkcjonalnie równoważny” mam na myśli właśnie to, w co kompilator zamienia kod. Nie można używać foreach
na baz
w tym przykładzie chyba baz
narzędzi IEnumerable
.
IEnumerable
oznacza, że baz
implementuje metodę
IEnumerator GetEnumerator()
IEnumerator
Obiektem że metoda ta zwraca musi implementować metody
bool MoveNext()
i
Object Current()
Pierwsza metoda przechodzi do następnego obiektu w IEnumerable
obiekcie, który utworzył moduł wyliczający, zwracając, false
jeśli jest zrobiony, a druga zwraca bieżący obiekt.
Wszystko w .Net, które można iterować po implementacjach IEnumerable
. Jeśli budujesz własną klasę, która nie dziedziczy już po klasie, która się implementuje IEnumerable
, możesz uczynić ją użyteczną w foreach
instrukcjach, implementując IEnumerable
(i tworząc klasę wyliczającą, GetEnumerator
która zwróci jej nowa metoda).
bool MoveNext()
metodę i Current
właściwość dowolnego typu. To podejście „typowania kaczego” zostało zaimplementowane w C # 1.0 jako sposób uniknięcia boksu podczas wyliczania kolekcji typów wartości.
iterator
?
Interfejsy IEnumerable i IEnumerator
Aby rozpocząć badanie procesu wdrażania istniejących interfejsów .NET, najpierw przyjrzyjmy się roli IEnumerable i IEnumerator. Przypomnij sobie, że C # obsługuje słowo kluczowe o nazwie foreach, które pozwala iterować po zawartości dowolnego typu tablicy:
// Iterate over an array of items.
int[] myArrayOfInts = {10, 20, 30, 40};
foreach(int i in myArrayOfInts)
{
Console.WriteLine(i);
}
Chociaż może się wydawać, że tylko typy tablic mogą korzystać z tego konstruktu, prawda jest taka, że każdy typ obsługujący metodę o nazwie GetEnumerator () może zostać oceniony przez konstrukcję foreach. Aby to zilustrować, podążaj za mną!
Załóżmy, że mamy klasę Garaż:
// Garage contains a set of Car objects.
public class Garage
{
private Car[] carArray = new Car[4];
// Fill with some Car objects upon startup.
public Garage()
{
carArray[0] = new Car("Rusty", 30);
carArray[1] = new Car("Clunker", 55);
carArray[2] = new Car("Zippy", 30);
carArray[3] = new Car("Fred", 30);
}
}
Idealnie byłoby iterować podelementy obiektu Garage za pomocą konstrukcji foreach, podobnie jak tablica wartości danych:
// This seems reasonable ...
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Fun with IEnumerable / IEnumerator *****\n");
Garage carLot = new Garage();
// Hand over each car in the collection?
foreach (Car c in carLot)
{
Console.WriteLine("{0} is going {1} MPH",
c.PetName, c.CurrentSpeed);
}
Console.ReadLine();
}
}
Niestety kompilator informuje, że klasa Garage nie implementuje metody o nazwie GetEnumerator (). Ta metoda jest sformalizowana przez interfejs IEnumerable, który znajduje się w przestrzeni nazw System.Collections. Klasy lub struktury, które obsługują to zachowanie, reklamują, że są w stanie udostępnić wywołującym zawarte elementy podrzędne (w tym przykładzie samo słowo kluczowe foreach). Oto definicja tego standardowego interfejsu .NET:
// This interface informs the caller
// that the object's subitems can be enumerated.
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
Jak widać, metoda GetEnumerator () zwraca odwołanie do jeszcze innego interfejsu o nazwie System.Collections.IEnumerator. Ten interfejs zapewnia infrastrukturę umożliwiającą rozmówcy przechodzenie przez wewnętrzne obiekty zawarte w kontenerze kompatybilnym z IEnumerable:
// This interface allows the caller to
// obtain a container's subitems.
public interface IEnumerator
{
bool MoveNext (); // Advance the internal position of the cursor.
object Current { get;} // Get the current item (read-only property).
void Reset (); // Reset the cursor before the first member.
}
Jeśli chcesz zaktualizować typ garażu, aby obsługiwał te interfejsy, możesz przejść długą drogę i zaimplementować każdą metodę ręcznie. Chociaż z pewnością masz swobodę dostarczania niestandardowych wersji GetEnumerator (), MoveNext (), Current i Reset (), istnieje prostszy sposób. Ponieważ typ System.Array (jak również wiele innych klas kolekcji) już implementuje IEnumerable i IEnumerator, możesz po prostu delegować żądanie do System.Array w następujący sposób:
using System.Collections;
...
public class Garage : IEnumerable
{
// System.Array already implements IEnumerator!
private Car[] carArray = new Car[4];
public Garage()
{
carArray[0] = new Car("FeeFee", 200);
carArray[1] = new Car("Clunker", 90);
carArray[2] = new Car("Zippy", 30);
carArray[3] = new Car("Fred", 30);
}
public IEnumerator GetEnumerator()
{
// Return the array object's IEnumerator.
return carArray.GetEnumerator();
}
}
Po zaktualizowaniu typu garażu możesz bezpiecznie używać go w konstrukcji Cach foreach. Ponadto, biorąc pod uwagę, że metoda GetEnumerator () została zdefiniowana publicznie, użytkownik obiektu może również wchodzić w interakcje z typem IEnumerator:
// Manually work with IEnumerator.
IEnumerator i = carLot.GetEnumerator();
i.MoveNext();
Car myCar = (Car)i.Current;
Console.WriteLine("{0} is going {1} MPH", myCar.PetName, myCar.CurrentSpeed);
Jeśli jednak wolisz ukryć funkcjonalność IEnumerable na poziomie obiektu, po prostu skorzystaj z jawnej implementacji interfejsu:
IEnumerator IEnumerable.GetEnumerator()
{
// Return the array object's IEnumerator.
return carArray.GetEnumerator();
}
W ten sposób przypadkowy użytkownik obiektu nie znajdzie metody GarEnumerator () Garage, podczas gdy konstrukcja foreach uzyska interfejs w tle, gdy będzie to konieczne.
Na podstawie Pro C # 5.0 i .NET 4.5 Framework
Garage
który pobiera carArray
? W ten sposób nie musisz się wdrażać GetEnumerator
, ponieważ Array
już to robi. Egforeach(Car c in carLot.getCars()) { ... }
Implementacja IEnumerable oznacza, że twoja klasa zwraca obiekt IEnumerator:
public class People : IEnumerable
{
IEnumerator IEnumerable.GetEnumerator()
{
// return a PeopleEnumerator
}
}
Wdrożenie IEnumerator oznacza, że klasa zwraca metody i właściwości dla iteracji:
public class PeopleEnumerator : IEnumerator
{
public void Reset()...
public bool MoveNext()...
public object Current...
}
To i tak różnica.
Najpierw wyjaśnienie bez kodu, a następnie dodam je później.
Powiedzmy, że prowadzisz linię lotniczą. I w każdym samolocie chcesz znać informacje o pasażerach lecących samolotem. Zasadniczo chcesz być w stanie „przemierzać” samolot. Innymi słowy, chcesz móc zacząć na przednim siedzeniu, a następnie skierować się do tyłu samolotu, prosząc pasażerów o informacje: kim oni są, skąd pochodzą itp. Samolot może to zrobić tylko , Jeśli to jest:
Dlaczego te wymagania? Ponieważ tego wymaga interfejs.
Jeśli jest to przeciążenie informacją, wystarczy wiedzieć, że chcesz zadać każdemu pasażerowi w samolocie kilka pytań, zaczynając od pierwszego do ostatniej.
Co znaczy liczyć?
Jeśli linia lotnicza jest „policzalna”, oznacza to, że MUSI być obecny stewardesa w samolocie, którego jedynym zadaniem jest liczyć - a stewardesa MUSI liczyć w bardzo szczególny sposób:
Procedury liczenia
Kapitan linii lotniczej chce sporządzić raport na temat każdego pasażera w momencie, gdy zostaną zbadani lub policzeni. Tak więc po rozmowie z osobą na pierwszym miejscu stewardesa / licznik następnie zgłasza się do kapitana, a gdy przekazany jest raport, licznik pamięta swoją dokładną pozycję w przejściu i kontynuuje liczenie od miejsca, w którym wyszedł poza.
W ten sposób kapitan zawsze może uzyskać informacje o bieżącej osobie, która jest przesłuchiwana. W ten sposób, jeśli dowie się, że ta osoba lubi Manchester City, może udzielić pasażerowi preferencyjnego traktowania itp.
Połączmy to z IEnumerables
Wyliczenie to tylko zbiór pasażerów w samolocie. Prawo o lotnictwie cywilnym - są to w zasadzie zasady, których muszą przestrzegać wszystkie numery IE. Za każdym razem, gdy stewardesa podchodzi do kapitana z informacją pasażera, w zasadzie „oddajemy” pasażera kapitanowi. Kapitan może w zasadzie robić wszystko, co chce z pasażerem - z wyjątkiem zmiany rozmieszczenia pasażerów w samolocie. W takim przypadku są traktowani preferencyjnie, jeśli podążają za Manchester City (ugh!)
foreach (Passenger passenger in Plane)
// the airline hostess is now at the front of the plane
// and slowly making her way towards the back
// when she get to a particular passenger she gets some information
// about the passenger and then immediately heads to the cabin
// to let the captain decide what to do with it
{ // <---------- Note the curly bracket that is here.
// we are now cockpit of the plane with the captain.
// the captain wants to give the passenger free
// champaign if they support manchester city
if (passenger.supports_mancestercity())
{
passenger.getFreeChampaign();
} else
{
// you get nothing! GOOD DAY SIR!
}
} // <---- Note the curly bracket that is here!
the hostess has delivered the information
to the captain and goes to the next person
on the plane (if she has not reached the
end of the plane)
Podsumowanie
Innymi słowy, coś można policzyć, jeśli ma licznik . I licznik musi (w zasadzie): (i) zapamiętać swoje miejsce ( stan ), (ii) móc przejść dalej , (iii) i wiedzieć o obecnej osobie, z którą ma do czynienia.
Wyliczenie to tylko wymyślne słowo na „policzalny”. Innymi słowy, wyliczalny pozwala „wyliczyć” (tj. Policzyć).
IEnumerable implementuje GetEnumerator. Po wywołaniu ta metoda zwróci IEnumerator, który implementuje MoveNext, Reset i Current.
Tak więc, gdy twoja klasa implementuje IEnumerable, mówisz, że możesz wywołać metodę (GetEnumerator) i otrzymać nowy obiekt (IEnumerator), którego możesz użyć w pętli, takiej jak foreach.
Implementacja IEnumerable umożliwia uzyskanie IEnumeratora dla listy.
IEnumerator pozwala na sekwencyjny dostęp do stylu foreach dla elementów na liście przy użyciu słowa kluczowego fed.
Przed implementacją foreach (na przykład w Javie 1.4) sposobem na iterację listy było pobranie enumeratora z listy, a następnie poproszenie go o pozycję „następną” na liście, o ile wartość zwracana jest jako następna pozycja nie jest pusta. Foreach robi to po prostu niejawnie jako funkcję języka, w taki sam sposób, w jaki lock () implementuje klasę Monitor za scenami.
Spodziewam się, że foreach działa na listach, ponieważ implementują IEnumerable.
Pomyśl o obiektach policzalnych jak o listach, stosach, drzewach.
IEnumerable i IEnumerator (i ich ogólne odpowiedniki IEnumerable <T> i IEnumerator <T>) są podstawowymi interfejsami implementacji iteratora w kolekcjach Libray klasy .Net Framework .
IEnumerable to najczęstszy interfejs, który można zobaczyć w większości kodu. Umożliwia pętlę foreach, generatory (myśl wydajność ), a ze względu na mały interfejs służy do tworzenia ścisłych abstrakcji. IEnumerable zależy od IEnumerator .
Z drugiej strony IEnumerator zapewnia interfejs iteracji nieco niższego poziomu. Jest to określane jako jawny iterator, który daje programiście większą kontrolę nad cyklem iteracji.
IEnumerable to standardowy interfejs, który umożliwia iterację po kolekcjach, które go obsługują (w rzeczywistości wszystkie typy kolekcji, o których dziś myślę, implementują IEnumerable ). Obsługa kompilatora umożliwia takie funkcje językowe jak foreach
. Ogólnie rzecz biorąc, umożliwia to niejawną implementację iteratora .
foreach (var value in list)
Console.WriteLine(value);
Myślę, że foreach
pętla jest jednym z głównych powodów używania interfejsów IEnumerable . foreach
ma bardzo zwięzłą składnię i jest bardzo łatwy do zrozumienia w porównaniu do klasycznego stylu C dla pętli, w których musisz sprawdzić różne zmienne, aby zobaczyć, co robi.
Prawdopodobnie mniej znaną cechą jest to, że IEnumerable włącza również generatory w języku C # za pomocą instrukcji yield return
i yield break
.
IEnumerable<Thing> GetThings() {
if (isNotReady) yield break;
while (thereIsMore)
yield return GetOneMoreThing();
}
Innym częstym scenariuszem w praktyce jest użycie IEnumerable w celu zapewnienia minimalistycznych abstrakcji. Ponieważ jest to niewielki interfejs i tylko do odczytu, zachęca się do ujawnienia swoich kolekcji jako IEnumerable (zamiast na przykład List ). W ten sposób możesz swobodnie zmieniać swoją implementację bez łamania kodu klienta ( na przykład zmień List na LinkedList ).
Jednym z zachowań, o których należy pamiętać, jest to, że w implementacjach przesyłania strumieniowego (np. Pobieranie danych wiersz po rzędzie z bazy danych, zamiast ładowania wszystkich wyników do pamięci w pierwszej kolejności) nie można iterować kolekcji więcej niż jeden raz. Jest to sprzeczne z kolekcjami w pamięci, takimi jak Lista , w których można iterować wiele razy bez problemów. Na przykład ReSharper ma kontrolę kodu pod kątem możliwego wielokrotnego wyliczenia IEnumerable .
Z drugiej strony IEnumerator to interfejs, który sprawia, że IEnumerble-foreach-magic działa. Ściśle mówiąc, umożliwia jawne iteratory.
var iter = list.GetEnumerator();
while (iter.MoveNext())
Console.WriteLine(iter.Current);
Z mojego doświadczenia wynika, że IEnumerator jest rzadko używany w typowych scenariuszach ze względu na bardziej szczegółową składnię i nieco mylącą semantykę (przynajmniej dla mnie; np. MoveNext () również zwraca wartość, której nazwa wcale nie sugeruje).
Korzystałem tylko z bibliotek IEnumerator, w szczególności (nieco niższego poziomu) bibliotek i frameworków, w których zapewniałem interfejsy IEnumerable . Jednym z przykładów jest biblioteka przetwarzania strumienia danych, która zapewniała szereg obiektów w foreach
pętli, mimo że za kulisami dane były zbierane przy użyciu różnych strumieni plików i serializacji.
Kod klienta
foreach(var item in feed.GetItems())
Console.WriteLine(item);
Biblioteka
IEnumerable GetItems() {
return new FeedIterator(_fileNames)
}
class FeedIterator: IEnumerable {
IEnumerator GetEnumerator() {
return new FeedExplicitIterator(_stream);
}
}
class FeedExplicitIterator: IEnumerator {
DataItem _current;
bool MoveNext() {
_current = ReadMoreFromStream();
return _current != null;
}
DataItem Current() {
return _current;
}
}
Implementacja IEnumerable
zasadniczo oznacza, że obiekt może być iterowany. Nie musi to oznaczać, że jest to tablica, ponieważ istnieją pewne listy, których nie można indeksować, ale można je wyliczyć.
IEnumerator
jest rzeczywistym obiektem używanym do wykonywania iteracji. Kontroluje przechodzenie od jednego obiektu do drugiego na liście.
Przez większość czasu IEnumerable
& IEnumerator
są używane w sposób przezroczysty jako część foreach
pętli.
Różnice między IEnumerable i IEnumerator:
Ilekroć przekazujemy kolekcję IEnumerable do innej funkcji, nie zna ona aktualnej pozycji elementu / obiektu (nie wie, który element wykonuje)
IEnumerable ma jedną metodę GetEnumerator ()
public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); }
IEnumerator ma jedną właściwość o nazwie Bieżąca i dwie metody: Reset () i MoveNext () (co jest przydatne do poznania aktualnej pozycji elementu na liście).
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
IEnumerable to pole zawierające Ienumerator. IEnumerable to podstawowy interfejs dla wszystkich kolekcji. Pętla foreach może działać, jeśli kolekcja implementuje IEnumerable. W poniższym kodzie wyjaśniono etap posiadania własnego modułu wyliczającego. Najpierw określmy naszą klasę, której kolekcję będziemy tworzyć.
public class Customer
{
public String Name { get; set; }
public String City { get; set; }
public long Mobile { get; set; }
public double Amount { get; set; }
}
Teraz zdefiniujemy klasę, która będzie działać jako kolekcja dla naszego klienta klasy. Zauważ, że implementuje interfejs IEnumerable. Dlatego musimy wdrożyć metodę GetEnumerator. Zwróci to nasz niestandardowy moduł wyliczający.
public class CustomerList : IEnumerable
{
Customer[] customers = new Customer[4];
public CustomerList()
{
customers[0] = new Customer { Name = "Bijay Thapa", City = "LA", Mobile = 9841639665, Amount = 89.45 };
customers[1] = new Customer { Name = "Jack", City = "NYC", Mobile = 9175869002, Amount = 426.00 };
customers[2] = new Customer { Name = "Anil min", City = "Kathmandu", Mobile = 9173694005, Amount = 5896.20 };
customers[3] = new Customer { Name = "Jim sin", City = "Delhi", Mobile = 64214556002, Amount = 596.20 };
}
public int Count()
{
return customers.Count();
}
public Customer this[int index]
{
get
{
return customers[index];
}
}
public IEnumerator GetEnumerator()
{
return customers.GetEnumerator(); // we can do this but we are going to make our own Enumerator
return new CustomerEnumerator(this);
}
}
Teraz stworzymy własny niestandardowy moduł wyliczający w następujący sposób. Musimy więc zaimplementować metodę MoveNext.
public class CustomerEnumerator : IEnumerator
{
CustomerList coll;
Customer CurrentCustomer;
int currentIndex;
public CustomerEnumerator(CustomerList customerList)
{
coll = customerList;
currentIndex = -1;
}
public object Current => CurrentCustomer;
public bool MoveNext()
{
if ((currentIndex++) >= coll.Count() - 1)
return false;
else
CurrentCustomer = coll[currentIndex];
return true;
}
public void Reset()
{
// we dont have to implement this method.
}
}
Teraz możemy użyć pętli foreach w naszej kolekcji, jak poniżej;
class EnumeratorExample
{
static void Main(String[] args)
{
CustomerList custList = new CustomerList();
foreach (Customer cust in custList)
{
Console.WriteLine("Customer Name:"+cust.Name + " City Name:" + cust.City + " Mobile Number:" + cust.Amount);
}
Console.Read();
}
}
Zrozumienie wzoru Iteratora będzie dla ciebie pomocne. Polecam przeczytać to samo.
Na wysokim poziomie wzorzec iteratora może być używany do zapewnienia standardowego sposobu iteracji przez kolekcje dowolnego typu. Mamy 3 uczestników wzorca iteratora, faktycznej kolekcji (klienta), agregatora i iteratora. Agregat to klasa interfejsu / abstrakcyjna, która ma metodę zwracającą iterator. Iterator to klasa interfejsu / abstrakcyjna, która ma metody pozwalające na iterację w kolekcji.
Aby zaimplementować wzorzec, musimy najpierw zaimplementować iterator, aby uzyskać konkretny element, który może iterować po danej kolekcji (kliencie). Następnie kolekcja (klient) implementuje agregator, aby zwrócić instancję powyższego iteratora.
Więc w zasadzie w c #, IEnumerable jest abstrakcyjnym agregatem, a IEnumerator jest abstrakcyjnym Iteratorem. IEnumerable ma jedną metodę GetEnumerator, która jest odpowiedzialna za utworzenie instancji IEnumerator żądanego typu. Kolekcje takie jak Listy implementują IEnumerable.
Przykład. Załóżmy, że mamy metodę, getPermutations(inputString)
która zwraca wszystkie permutacje łańcucha i że metoda zwraca instancjęIEnumerable<string>
Aby policzyć liczbę permutacji, możemy zrobić coś takiego jak poniżej.
int count = 0;
var permutations = perm.getPermutations(inputString);
foreach (string permutation in permutations)
{
count++;
}
Kompilator c # mniej więcej konwertuje powyższe na
using (var permutationIterator = perm.getPermutations(input).GetEnumerator())
{
while (permutationIterator.MoveNext())
{
count++;
}
}
Jeśli masz jakieś pytania, nie wahaj się zadać.
Niewielki wkład.
Ponieważ wiele z nich wyjaśnia „kiedy używać” i „używać z foreach”. Pomyślałem o dodaniu tutaj innej różnicy stanów, o co pytano w pytaniu o różnicę między IEnumerable IEnumerator.
Utworzyłem poniższy przykład kodu na podstawie poniższych wątków dyskusji.
IEnumerable, IEnumerator vs foreach, kiedy używać Jaka jest różnica między IEnumerator a IEnumerable?
Moduł wyliczający zachowuje stan (pozycję iteracji) między wywołaniami funkcji, podczas gdy iteracje z drugiej strony nie.
Oto przetestowany przykład z komentarzami do zrozumienia.
Eksperci, dodaj mnie / popraw mnie.
static void EnumerableVsEnumeratorStateTest()
{
IList<int> numList = new List<int>();
numList.Add(1);
numList.Add(2);
numList.Add(3);
numList.Add(4);
numList.Add(5);
numList.Add(6);
Console.WriteLine("Using Enumerator - Remembers the state");
IterateFrom1to3(numList.GetEnumerator());
Console.WriteLine("Using Enumerable - Does not Remembers the state");
IterateFrom1to3Eb(numList);
Console.WriteLine("Using Enumerable - 2nd functions start from the item 1 in the collection");
}
static void IterateFrom1to3(IEnumerator<int> numColl)
{
while (numColl.MoveNext())
{
Console.WriteLine(numColl.Current.ToString());
if (numColl.Current > 3)
{
// This method called 3 times for 3 items (4,5,6) in the collection.
// It remembers the state and displays the continued values.
IterateFrom3to6(numColl);
}
}
}
static void IterateFrom3to6(IEnumerator<int> numColl)
{
while (numColl.MoveNext())
{
Console.WriteLine(numColl.Current.ToString());
}
}
static void IterateFrom1to3Eb(IEnumerable<int> numColl)
{
foreach (int num in numColl)
{
Console.WriteLine(num.ToString());
if (num>= 5)
{
// The below method invokes for the last 2 items.
//Since it doesnot persists the state it will displays entire collection 2 times.
IterateFrom3to6Eb(numColl);
}
}
}
static void IterateFrom3to6Eb(IEnumerable<int> numColl)
{
Console.WriteLine();
foreach (int num in numColl)
{
Console.WriteLine(num.ToString());
}
}
Zauważyłem te różnice:
Odp .: Iterujemy listę w inny sposób, foreach może być użyty dla IEnumerable, a while dla IEnumerator.
B. IEnumerator może zapamiętać bieżący indeks, kiedy przechodzimy z jednej metody do drugiej (zaczyna działać z bieżącym indeksem), ale IEnumerable nie może zapamiętać indeksu i resetuje indeks do początku. Więcej w tym wideo https://www.youtube.com/watch?v=jd3yUjGc9M0
IEnumerable
i IEnumerator
oba są interfejsami w języku C #.
IEnumerable
to interfejs definiujący pojedynczą metodę GetEnumerator()
zwracającą IEnumerator
interfejs.
Działa to w przypadku dostępu tylko do odczytu do kolekcji, której implementacje IEnumerable
mogą być używane z foreach
instrukcją.
IEnumerator
ma dwie metody MoveNext
i Reset
. Ma również właściwość o nazwie Current
.
Poniżej przedstawiono implementację IEnumerable i IEnumerator.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Enudemo
{
class Person
{
string name = "";
int roll;
public Person(string name, int roll)
{
this.name = name;
this.roll = roll;
}
public override string ToString()
{
return string.Format("Name : " + name + "\t Roll : " + roll);
}
}
class Demo : IEnumerable
{
ArrayList list1 = new ArrayList();
public Demo()
{
list1.Add(new Person("Shahriar", 332));
list1.Add(new Person("Sujon", 333));
list1.Add(new Person("Sumona", 334));
list1.Add(new Person("Shakil", 335));
list1.Add(new Person("Shruti", 336));
}
IEnumerator IEnumerable.GetEnumerator()
{
return list1.GetEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
Demo d = new Demo(); // Notice here. it is simple object but for
//IEnumerator you can get the collection data
foreach (Person X in d)
{
Console.WriteLine(X);
}
Console.ReadKey();
}
}
}
/*
Output :
Name : Shahriar Roll : 332
Name : Sujon Roll : 333
Name : Sumona Roll : 334
Name : Shakil Roll : 335
Name : Shruti Roll : 336
*/