Rozróżnienie między iteratorem a enumeratorem

Pytanie na rozmowę kwalifikacyjną dla zadania. NET 3.5 brzmi "jaka jest różnica między iteratorem a enumeratorem"?

To jest podstawowe rozróżnienie, co z LINQ itp.

W każdym razie, co za różnica? Nie mogę znaleźć solidnej definicji w sieci. Nie popełnij błędu, mogę znaleźć znaczenie tych dwóch terminów, ale dostaję nieco inne odpowiedzi. Jaka byłaby najlepsza odpowiedź na rozmowę kwalifikacyjną?

IMO iterator "iterata" nad zbiorem, a enumerator zapewnia funkcjonalność do iteracji, ale to musi być wywołane.

Również użycie słowa kluczowego yield mówi się, aby zapisać stan. Co to za stan? Czy istnieje przykład takiej korzyści?

Author: Zero Piraeus, 2009-04-04

8 answers

Iteracja oznacza powtarzanie pewnych kroków, podczas gdy wyliczanie oznacza przechodzenie przez wszystkie wartości w zbiorze wartości. Tak więc wyliczanie zwykle wymaga jakiejś formy iteracji.

W ten sposób, wyliczanie jest szczególnym przypadkiem iteracji, gdzie krok otrzymuje wartość ze zbioru.

Zauważ, że" zwykle " – wyliczanie może być również wykonywane rekurencyjnie, ale rekurencja i iteracja są tak blisko ze sobą powiązane, że nie przejmowałbym się tą małą różnicą.

Możesz wylicz również wartości, których nie przechowujesz jawnie w kolekcji. Na przykład, możesz wyliczyć liczbę naturalną, liczbę pierwszą lub cokolwiek innego, ale możesz obliczyć te wartości podczas wyliczania i nie pobierać ich z fizycznego zbioru. Rozumiesz ten przypadek jako wyliczenie wirtualnej kolekcji z jej wartościami zdefiniowanymi przez jakąś logikę.
Zakładam, że Reed Copsey zrozumiał. W C# są dwa główne sposoby wyliczenia czegoś.
  1. implementacja Enumerable i a class implementing IEnumerator
  2. zaimplementuj iterator za pomocą instrukcji yield

Pierwszy sposób jest trudniejszy do zaimplementowania i używa obiektów do wyliczania. Drugi sposób jest łatwiejszy do wdrożenia i wykorzystuje kontynuacje.

 46
Author: Daniel Brückner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-11 19:46:29

W C# 2+, Iteratory są sposobem na automatyczne generowanie interfejsów IEnumerable i/lub IEnumerable.

Bez iteratorów, trzeba by utworzyć klasę implementującą IEnumerator , w tym Current, MoveNext i Reset. Wymaga to sporo pracy. Zwykle tworzysz prywatną klasę, która implementuje IEnumerator dla Twojego typu, a następnie yourClass.GetEnumerator() zbuduje tę klasę prywatną i zwróci to.

Iteratory są dla kompilatora sposobem na automatyczne wygenerowanie tego za ciebie, używając prostej składni (yield). To pozwala Ci zaimplementować GetEnumerator () bezpośrednio w twojej klasie, bez podania drugiej klasy (IEnumerator). Budowa tej klasy, ze wszystkimi jej członkami, jest zrobiona za Ciebie.

Iteratory są bardzo przyjazne dla programistów - wszystko odbywa się w bardzo wydajny sposób, przy znacznie mniejszym wysiłku.

Kiedy użyjesz foreach, oba będą zachowywać się identycznie (pod warunkiem, że poprawnie napiszesz swój Niestandardowy Numerator). Iteratory ułatwiają życie.

 43
Author: Reed Copsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-04 01:18:22

To, co C# nazywa iteratorem jest częściej (poza światem C#) nazywane generator lub funkcja generatora (np. w Pythonie). Funkcja generatora jest szczególnym przypadkiem coroutine. Iterator (generator) C# jest specjalną formą enumeratora (typu danych implementującego interfejs IEnumerable).

Nie podoba mi się to użycie terminu iterator dla generatora C#, ponieważ jest on tak samo enumeratorem jak iterator. Za późno, by Microsoft zmienił zdanie.

Dla kontrastu weź pod uwagę, że w C++ iterator jest wartością, która jest używana głównie do dostępu do elementów sekwencyjnych w kolekcji. Może być zaawansowany, derferenced, aby pobrać wartość, i testowane, aby zobaczyć, czy koniec kolekcji został osiągnięty.

 16
Author: cdiggins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-27 11:50:48

Aby zrozumieć Iteratory musimy najpierw zrozumieć enumeratory.

Enumeratory to wyspecjalizowane obiekty, które umożliwiają poruszanie się po uporządkowanej liście przedmiotów pojedynczo (ten sam rodzaj rzeczy jest czasami nazywany "kursorem"). . NET Framework zapewnia dwa ważne interfejsy związane z enumeratorami: IEnumerator i IEnumerable. Obiekty implementujące IEnumerator same w sobie są enumeratorami; wspierają następujące elementy:

  • Na właściwość Current, która wskazuje na pozycję na liście

  • Metoda MoveNext, która przesuwa bieżący element o jeden wzdłuż listy

  • Metoda resetuje, która przesuwa bieżący element do pozycji początkowej (która znajduje się przed pierwszym elementem).

Z drugiej strony Iteratory implementują wzorzec enumeratora. . NET 2.0 wprowadził iterator, który jest kompilatorem. Gdy obiekt enumerable wywołuje GetEnumerator, albo bezpośrednio lub pośrednio, kompilator generuje i zwraca odpowiedni obiekt iteratora. Opcjonalnie iterator może być połączony z obiektem enumerator i Enumerator.

Istotnym składnikiem bloku iteratora jest deklaracja wydajności. Jest jedna duża różnica między iteratorami a enumeratorami: Iteratory nie implementują metody Reset. Wywołanie metody Reset na iteratorze powoduje wyjątek.

Celem iteratorów jest umożliwienie łatwej implementacji enumeratorów. Jeśli metoda musi zwrócić enumerator lub klasę enumerable dla uporządkowanej listy pozycji, jest ona zapisywana tak, aby zwracać każdy element w prawidłowej kolejności za pomocą instrukcji 'yield'.

 12
Author: Joshua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-04 01:25:23

" podczas gdy twierdzenie foreach jest konsumentem enumeratora, iterator jest producentem enumeratora."

Z powyższego wynika, że "C# 5.0 w pigułce" to wyjaśnia i jest dla mnie pomocne.

Innymi słowy, Instrukcja foreach używa MoveNext () i bieżącej właściwości IEnumerator do iteracji poprzez sekwencję, podczas gdy iterator jest używany do wytworzenia implementacji IEnumerator, która będzie używana przez instrukcję foreach. W C#, kiedy piszesz metoda iterator zawierająca instrukcję yield, kompilator wygeneruje dla Ciebie prywatny enumerator. I kiedy iterujesz przez elementy w sekwencji, wywoła ona właściwość MoveNext () i Current prywatnego enumeratora. Te metody / właściwości są zaimplementowane przez Twój kod w metodzie iterator, która będzie wywoływana powtarzalnie do wartości yield, dopóki nie zostaną żadne wartości do yield.

To jest moje zrozumienie jak C# definiuje enumeratory i Iteratory.

 10
Author: Ping,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-23 01:28:12

Ponieważ nie podano przykładów, oto jeden, który był dla mnie pomocny.

Enumerator jest obiektem, który otrzymujesz, gdy dzwonisz .GetEnumerator() na klasie lub typie implementującym interfejs IEnumerator. Kiedy ten interfejs jest zaimplementowany, stworzyłeś cały kod niezbędny dla kompilatora, aby umożliwić Ci użycie foreach do "iteracji" nad twoją kolekcją.

Nie pomyl tego słowa 'iterate' z iteratorem. Zarówno Enumerator jak i iterator pozwalają na "iterate" Wyliczanie i iteracja są zasadniczo tym samym procesem, ale są zaimplementowane inaczej. Wyliczenie oznacza, że wszczepiłeś interfejs Ienumeratora. Iteracja oznacza, że stworzyłeś konstrukt iteratora w swojej klasie (pokazany poniżej) i wywołujesz foreach na swojej klasie, w tym czasie kompilator automatycznie tworzy funkcjonalność enumeratora dla Ciebie.

Zauważ również, że nie musisz robić kucania ze swoim licznikiem. Możesz dzwonić MyClass.GetEnumerator() przez cały dzień i robić nic z tym (Przykład:

IEnumerator myEnumeratorThatIWillDoNothingWith = MyClass.GetEnumerator()).

Zauważ również, że Twoja konstrukcja iteratora w twojej klasie jest używana tylko wtedy, gdy faktycznie jej używasz, tzn. wywołałeś foreach na swojej klasie.

Oto przykład iteratora z msdn :

public class DaysOfTheWeek : System.Collections.IEnumerable
{

     string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };

     //This is the iterator!!!
     public System.Collections.IEnumerator GetEnumerator()
     {
         for (int i = 0; i < days.Length; i++)
         {
             yield return days[i];
         }
     }

}

class TestDaysOfTheWeek
{
    static void Main()
    {
        // Create an instance of the collection class
        DaysOfTheWeek week = new DaysOfTheWeek();

        // Iterate with foreach - this is using the iterator!!! When the compiler
        //detects your iterator, it will automatically generate the Current, 
        //MoveNext and Dispose methods of the IEnumerator or IEnumerator<T> interface
        foreach (string day in week)
        {
            System.Console.Write(day + " ");
        }
    }
}
// Output: Sun Mon Tue Wed Thr Fri Sat
 7
Author: richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-03 00:23:55

" Iteratory to nowa funkcja w C # 2.0. Iterator to metoda, get accessor lub operator, który umożliwia obsługę foreach iteracji w klasie lub strukturze bez konieczności implementacji całego interfejsu IEnumerable. Zamiast tego udostępniasz tylko iterator, który po prostu przemierza struktury danych w twojej klasie. Gdy kompilator wykryje Twój iterator, automatycznie wygeneruje metody Current, MoveNext i Dispose interfejsu IEnumerable lub IEnumerable." - msdn

 3
Author: John Ellinwood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-04 01:12:30

Wyliczenie dotyczy obiektów, podczas gdy iteracja dotyczy tylko wartości. Wyliczenie jest używane, gdy używamy wektorowego hashtable etc, podczas gdy iteracja jest używana w pętli while dla pętli itp. Nigdy nie używałem słowa kluczowego yield, więc nie mogłem ci powiedzieć.

 2
Author: Kredns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-04 01:11:34