2009-01-06 9 views
7

Rozważmy dwie metody iteracyjnej z tych samych korpusów:Czy istnieje jakaś różnica między metodami iteratora, które zwracają liczbę IEnumerable <T> i IEnumerator <T>?

public static IEnumerable<int> It1() { 
    ... 
} 

public static IEnumerator<int> It2() { 
    ... 
} 

Czy istnieje okoliczność gdzie nazywając It2 różni się od wywoływania It1.GetEnumerator()?

Czy istnieje jakiś dobry powód, aby zdefiniować iterator jako IEnumerator<T> przez IEnumerable<T>? Jedyne, o czym mogę pomyśleć, to kiedy implementujesz IEnumerable<T>.GetEnumerator().

EDYTOWANIE: Metodami iteracyjnymi mam na myśli metody wykorzystujące konstrukcje yield return i yield break.

+0

Ściśle mówiąc implementacje metod nie może być taka sama. –

+0

Oczywiście, że może. public static IEnumerable It1() { zwrot plonu 1; } public static IEnumerator It2() { zwrot plonu 1; } –

+0

Teraz to, co kompilator konwertuje je w oczywisty sposób różni się; jeden zostaje przekonwertowany na anonimową klasę implementującą IEnumerator , a drugi na dwie anonimowe klasy implementujące IEnumerable i IEnumerator . Czy istnieje przypadek, w którym dwa IEnumeratory są różne? –

Odpowiedz

1

Zrobiłbyś to, gdybyś chciał zająć się pisaniem klasy otoki IEnumerable<T>.

Powiedzmy, że masz klasę, którą chcesz zrobić wyliczenie na nieskończenie:

public class EveryDateInTheFuture : IEnumerable<DateTime> 
{ 
    public EveryDateInTheFuture() { this.StartDate = DateTime.Today; } 

    public DateTime StartDate { get; set; } 

    public IEnumerator<DateTime> GetEnumerator() 
    { 
     while (true) 
     { 
      yield return date; 
      date = date.AddDays(1); 
     } 
    } 
} 
8

Jak wspomniano, nie można foreach nad IEnumerator<T>. Z tego powodu utrudnia integrację z miejscami w kodzie, gdzie chcesz powtórzyć to, co powracasz.

Również imporance tutaj jest to, że IEnumerable<T> ma być fabrycznie, dzięki czemu można tworzyć implementacje IEnumerator<T>, które nie są bezpośrednio związane z realizacją kolekcji T.

Jeszcze ważniejsze jest to, że wszystkie metody rozszerzeń dla LINQ działają od IEnumerable<T>, więc będziesz chciał, aby twoje wyliczenia były jak najprostsze w użyciu, zwracając je.

+0

Tak, to jest dobry powód, aby preferować IEnumerable przez IEnumerator . Dlatego zapytałem o przeciwny kierunek. –

Powiązane problemy