Krótki przykład pokazujący na czym polega leniwe wartościowanie w LINQ-u w C#.
Najpierw tworzymy kolekcję, którą będzie zwracała elementy w nieskończoność. Iterowanie po tej kolekcji nigdy się nie skończy(sky(Cloud) is the limit).
public static class NieskonczonaKolekcja { private static float liczba; public static IEnumerable<float> DajKolekcje() { while (true) { liczba = liczba + 1; yield return liczba; } } }
Następnie tworzymy obiekt na którym zobrazujemy leniwe wartościowanie.
public class LeniweWartosciowanie { public LeniweWartosciowanie() { var nieskonczonaKolekcja = NieskonczonaKolekcja.DajKolekcje(); var kolekcja = nieskonczonaKolekcja .Where(k => k > 400) .Where(k => k % 2 == 0); foreach (var k in kolekcja) { Console.WriteLine(k); } } }
Co widzimy. Tworzymy implementację nieskończonej kolekcji a następnie wykonujemy na tej kolekcji filtrowanie wartości.
Najpierw filtrujemy elementy na podstawię tego czy są większe od 400 a później filtrujemy tyko liczby parzyste.
Na końcu iterujemy po kolekcji i ją wyświetlamy.
Najciekawsza jest linijka gdzie zwracamy kolekcję.
var nieskonczonaKolekcja = NieskonczonaKolekcja.DajKolekcje();
W tym miejscu dzieje się najważniejsze. Zwracamy nieskończoną kolekcję. Gdyby ta kolekcja była tworzona od razu, wtedy nigdy byśmy nie doszli do kolejnej operacji. Jednak tak się nie dzieje i program wykonuje się dalej.
Następna ciekawa linijka to iterowanie po kolekcji.
foreach (var k in kolekcja) { Console.WriteLine(k); }
Gdybyśmy debugowali kod zauważylibyśmy, że właśnie w tym miejscu zaczynamy wykonywać kod odpowiedzialny za zwracanie pierwszej wartości.
Mamy więc teraz pewność, że wykonywanie operacji na kolekcji zaczyna się dopiero gdy się do niej odwołujemy a nie gdy ją tworzymy lub wykonujemy operacje filtrowania.