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>lubIEnumerator<T>. - Każde
yield returnemituje 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
- Metody iteratorów z yield return
- yield break i wcześniejsze zakończenie
- Semantyka leniwej ewaluacji
- Niestandardowe typy wyliczalne