Leniwe wartościowanie (lazy evaluation) w LINQ

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.