0Pricing
C# Academy · Lekcja

Metody iteratorów z yield return

Generuj sekwencje po jednym elemencie naraz.

Metody iteratorów z yield return to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.

Czym jest metoda iteratora

Metoda iteratora generuje sekwencję wartości pojedynczo za pomocą yield return. Kompilator przekształca ją w maszynę stanów, dzięki czemu nie trzeba samodzielnie tworzyć listy ani nią zarządzać.

Pierwsze yield return

Każde yield return przekazuje wywołującemu jedną wartość i wstrzymuje metodę. Przy następnej iteracji wykonywanie jest wznawiane bezpośrednio po tej instrukcji.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> FirstThree()
    {
        yield return 1;
        yield return 2;
        yield return 3;
    }

    public static void Main()
    {
        foreach (var n in FirstThree())
            Console.WriteLine(n);
    }
}

yield return wewnątrz pętli

Większość iteratorów zwraca wartości wewnątrz pętli. W tym przykładzie generowanych jest pierwszych count liczb parzystych bez tworzenia kolekcji.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Evens(int count)
    {
        for (int i = 0; i < count; i++)
            yield return i * 2;
    }

    public static void Main()
    {
        foreach (var n in Evens(5))
            Console.WriteLine(n);
    }
}

Metoda zwraca IEnumerable

Metoda iteratora musi zwracać IEnumerable<T> lub IEnumerator<T> (albo ich niegeneryczne odpowiedniki). Nie należy używać return z wartością; można używać wyłącznie yield return.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<string> Greetings()
    {
        yield return "hello";
        yield return "hi";
        yield return "hey";
    }

    public static void Main()
    {
        foreach (var g in Greetings())
            Console.WriteLine(g);
    }
}

Wykonywanie jest wstrzymywane i wznawiane

Stan pomiędzy kolejnymi zwróconymi wartościami jest zachowywany automatycznie. Zmienne lokalne zachowują wartości podczas wstrzymań, co ułatwia generowanie sum narastających.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> RunningTotal(IEnumerable<int> nums)
    {
        int total = 0;
        foreach (var n in nums)
        {
            total += n;
            yield return total;
        }
    }

    public static void Main()
    {
        foreach (var t in RunningTotal(new[] { 1, 2, 3, 4 }))
            Console.WriteLine(t);
    }
}

Generowanie nieskończonych sekwencji

Ponieważ wartości są tworzone na żądanie, iterator może bezpiecznie opisywać nieskończoną sekwencję. To wywołujący decyduje, kiedy przestać pobierać wartości.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Naturals()
    {
        int i = 1;
        while (true) yield return i++;
    }

    public static void Main()
    {
        int taken = 0;
        foreach (var n in Naturals())
        {
            Console.WriteLine(n);
            if (++taken == 5) break;
        }
    }
}

Przekształcanie sekwencji wejściowej

Iteratory doskonale sprawdzają się przy budowaniu potoków: odczytują elementy z jednej sekwencji, przekształcają je i leniwie zwracają wyniki.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<string> Labelled(IEnumerable<int> nums)
    {
        foreach (var n in nums)
            yield return "item-" + n;
    }

    public static void Main()
    {
        foreach (var s in Labelled(new[] { 10, 20, 30 }))
            Console.WriteLine(s);
    }
}

Filtrowanie za pomocą iteratorów

Aby filtrować elementy, wystarczy zwracać tylko te, które są potrzebne. Pominięte elementy nigdy nie są generowane, więc kod znajdujący się dalej w potoku ich nie zobaczy.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> OnlyPositive(IEnumerable<int> nums)
    {
        foreach (var n in nums)
            if (n > 0) yield return n;
    }

    public static void Main()
    {
        foreach (var n in OnlyPositive(new[] { -2, 5, -1, 8 }))
            Console.WriteLine(n);
    }
}

Kompilator buduje maszynę stanów

W tle kompilator przepisuje iterator na klasę implementującą IEnumerator<T>, która śledzi ukryte pole stanu i wartość Current. Cała ta infrastruktura jest dostępna bez dodatkowego kodu.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<char> Letters()
    {
        yield return 'a';
        yield return 'b';
        yield return 'c';
    }

    public static void Main()
    {
        IEnumerator<char> e = Letters().GetEnumerator();
        while (e.MoveNext())
            Console.WriteLine(e.Current);
    }
}

Łączenie wielu iteratorów

Iteratory można naturalnie łączyć, ponieważ każdy z nich zwraca IEnumerable<T>. Wynik jednego iteratora można przekazać do następnego, aby tworzyć czytelne potoki.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Range(int start, int count)
    {
        for (int i = 0; i < count; i++) yield return start + i;
    }
    static IEnumerable<int> Squares(IEnumerable<int> nums)
    {
        foreach (var n in nums) yield return n * n;
    }

    public static void Main()
    {
        foreach (var n in Squares(Range(1, 4)))
            Console.WriteLine(n);
    }
}

Wypróbuj samodzielnie

Proszę napisać iterator, który grupuje sekwencję wejściową w porcje o stałym rozmiarze. Zwraca on listy na żądanie i pokazuje, jak wiele logiki można zawrzeć w jednym przejrzystym iteratorze.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<List<int>> Batch(IEnumerable<int> source, int size)
    {
        var bucket = new List<int>();
        foreach (var n in source)
        {
            bucket.Add(n);
            if (bucket.Count == size) { yield return bucket; bucket = new List<int>(); }
        }
        if (bucket.Count > 0) yield return bucket;
    }

    public static void Main()
    {
        foreach (var group in Batch(new[] { 1, 2, 3, 4, 5 }, 2))
            Console.WriteLine(string.Join(",", group));
    }
}

Szybkie sprawdzenie

Proszę przypomnieć sobie, jak działają metody iteratorów.

Podsumowanie

Metody iteratorów używają yield return do generowania sekwencji na żądanie.

  • Metoda zwraca IEnumerable<T> lub IEnumerator<T>.
  • Każde yield return emituje jedną wartość i wstrzymuje wykonywanie, zachowując stan lokalny.
  • Mogą bezpiecznie opisywać nieskończone sekwencje.
  • Kompilator generuje maszynę stanów automatycznie.

Często zadawane pytania

Czy lekcja „Metody iteratorów z yield return” jest bezpłatna?

Tak — pełny tekst „Metody iteratorów z yield return” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Metody iteratorów z yield return”?

Generuj sekwencje po jednym elemencie naraz. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C# Academy?

Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Metody iteratorów z yield return”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?

Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Metody iteratorów z yield return
  2. yield break i wcześniejsze zakończenie
  3. Semantyka leniwej ewaluacji
  4. Niestandardowe typy wyliczalne
← Powrót do C# Academy