2009-06-26 23 views
21

Sprawdzam kod w reflektorze, ale jeszcze nie wiem, jak można go wyliczyć poprzez kolekcję do tyłu?Jak działa IEnumerable <T>.

Ponieważ nie ma informacji o liczbie, a wyliczenie zawsze rozpoczyna się od "początku" kolekcji, prawda?

Czy to jest wadą platformy .NET? Czy koszt jest wyższy niż regularne wyliczanie?

+0

Nie ma IEnumerable . Metoda odwrotna, jakie kiedykolwiek widziałem (i MSDN wydaje się wspierać to)! – Noldorin

+8

To dlatego, że jest to metoda rozszerzenia: http://msdn.microsoft.com/en-us/library/bb358497.aspx –

+2

@Noldorin: Enumerable.Reverse jest metodą rozszerzenia na IEunumerable

Odpowiedz

40

Krótko mówiąc, buforuje wszystko, a następnie przechodzi przez nie do tyłu. Nie jest to efektywne, ale z drugiej strony nie można tego zrobić z tej perspektywy.

W LINQ-to-Objects dostępne są operacje buforowania (Reverse, OrderBy, GroupBy itp.) Oraz operacje bez buforowania (Where, Take, Skip, itp.).


Jako przykład nie-buforowania Reverse realizacji z wykorzystaniem IList<T> rozważyć:

public static IEnumerable<T> Reverse<T>(this IList<T> list) { 
    for (int i = list.Count - 1; i >= 0; i--) { 
     yield return list[i]; 
    } 
} 

Należy pamiętać, że jest to nadal mało podatne na błędy, jeśli mutować listę podczas iteracji go ... więc nie rób tego ;-p

+0

Dzięki Marc. Przez buforowanie masz na myśli to, że kopiuje całą kolekcję, jak mówi Levi? –

+3

Dokładnie tak, tak. –

+0

Dzięki Marc. Czy z ciekawości wiesz również, czy można dokonać lepszego wyliczenia za pomocą nowego interfejsu? Zawsze myślałem, że IEnumerable było dobre (i jest), ale czy byłby w stanie zaprojektować taki, który w tych przypadkach byłby lepszy? –

6

Działa poprzez skopiowanie podstawowej IEnumerable <T> do tablicy, a następnie wyliczenie tej tablicy wstecz. Jeśli podstawowy IEnumerable <T> implementuje ICollection <T> (jak T [], lista <T> itd.), To krok kopiowania jest pomijany, a moduł wyliczający tylko iteruje bezpośrednio nad kolekcją leżącą u podstaw.

Aby uzyskać więcej informacji, zobacz System.Linq.Buffer <TElement> w Reflectorze.

Edytuj: Podstawowa kolekcja jest zawsze kopiowana, nawet jeśli jest to ICollection <TElement>. Zapobiega to rozprzestrzenianiu się zmian w podstawowej kolekcji przez bufor <TElement>.

+0

Patrzę na ctor bufora i nie widzę czasu, kiedy pomija krok kopiowania - czy trzeba się zastanowić? –

+0

@Marc, @Levi: Nadal wykonuje kopię, ale robi to za pomocą metody ICollection .CopyTo zamiast wyliczać sekwencję. – LukeH

3

ładuje wszystkie przedmioty do pamięci, a następnie przechodzi przez nie (do tyłu). to znacznie mniej wydajne.

-3

Edytuj: Opps, napisał zły test na odwrót, moje przeprosiny za złą odpowiedź. Wykonuje bufor po przeprowadzeniu testu poprawności (użycie przelicznika zwróconego przez Reverse())

Wygląda na to, że metoda odwrotnego rozszerzenia działa tylko wtedy, gdy kolekcja jest wypełniona. Podczas korzystania z zwrotu z inwestycji nic nie robi.

Wystąpił problem przy użyciu odwrotnej myśli, że musi buforować, aby działał, okazało się, że nie działa z wydajnością. Po prostu go przepuszczaj i nic nie rób. poniżej jest mój kod testowy.

 [TestMethod] 
    public void loopTest() 
    { 
     var series = this.GetSeries(); 

     series.Reverse(); 

     foreach (var l in series) 
     { 
      Debug.WriteLine(l); 
     } 
    } 

    private IEnumerable<long> GetSeries() 
    { 
     var series = new List<long>() { 1, 2, 3, 4 }; 

     foreach (var entry in series) 
     { 
      Debug.WriteLine(entry); 

      yield return entry; 
     } 
    } 

Odwróć, nie wołaj funkcji GetSeries, wszystkie rozmowy o buforowaniu na tym forum wygląda z powietrza.

+1

Metoda odwrotnego przedłużenia nie odwraca właściwej kolekcji. Zamiast tego tworzy nowy przelicznik, który wyliczy kolekcję w odwrotnej kolejności. Twoja linia, która wygląda jak ta 'seria.Reverse();' nie działa. Jeśli zmienisz linię tak, aby wyglądała jak ta 'var odwrócona = series.Reverse();' a następnie iteruj po 'odwróconym', tnnie otrzymasz poprawną odpowiedź. – wageoghe

+0

Dziękuję wageoghe, za wskazanie problemu. – mamu

Powiązane problemy