Leniwa ocena / odroczone wykonanie
Bloki iteratora „yield return” nie wykonają żadnego kodu, dopóki nie wywołasz tego konkretnego wyniku. Oznacza to, że można je również skutecznie łączyć łańcuchami. Quiz: ile razy następujący kod będzie iterował po pliku?
var query = File.ReadLines(@"C:\MyFile.txt")
.Where(l => l.Contains("search text") )
.Select(l => int.Parse(l.SubString(5,8))
.Where(i => i > 10 );
int sum=0;
foreach (int value in query)
{
sum += value;
}
Odpowiedź jest dokładnie jedna, i to dopiero na końcu foreach
pętli. Mimo, że mam trzy oddzielne funkcje operatora linq, nadal przechodzimy przez zawartość pliku tylko raz.
Ma to inne zalety niż wydajność. Na przykład mogę napisać dość prostą i ogólną metodę jednorazowego odczytu i wstępnego przefiltrowania pliku dziennika i użyć tej samej metody w kilku różnych miejscach, gdzie każde użycie dodaje inne filtry. W ten sposób utrzymuję dobrą wydajność, jednocześnie efektywnie ponownie wykorzystując kod.
Nieskończone listy
Zobacz moją odpowiedź na to pytanie na dobry przykład:
funkcja C # Fibonacciego zwraca błędy
Zasadniczo implementuję sekwencję Fibonacciego za pomocą bloku iteratora, który nigdy się nie zatrzyma (przynajmniej nie przed osiągnięciem MaxInt), a następnie używam tej implementacji w bezpieczny sposób.
Ulepszona semantyka i separacja problemów
Ponownie, używając powyższego przykładu pliku, możemy teraz łatwo oddzielić kod, który odczytuje plik, od kodu, który odfiltrowuje niepotrzebne wiersze z kodu, który faktycznie analizuje wyniki. Szczególnie ten pierwszy jest bardzo przydatny do ponownego użycia.
Jest to jedna z tych rzeczy, które znacznie trudniej wyjaśnić prozą niż tylko komu za pomocą prostej grafiki 1 :
Jeśli nie widzisz obrazu, przedstawia dwie wersje tego samego kodu z podświetleniami w tle dla różnych problemów. W kodzie linq wszystkie kolory są ładnie pogrupowane, podczas gdy w tradycyjnym kodzie rozkazującym kolory są przeplatane. Autor argumentuje (i zgadzam się z tym), że ten wynik jest typowy dla używania linq kontra kod imperatywny ... że linq lepiej organizuje twój kod, aby mieć lepszy przepływ między sekcjami.
1 Uważam, że jest to oryginalne źródło: https://twitter.com/mariofusco/status/571999216039542784 . Zauważ również, że ten kod to Java, ale C # byłby podobny.