0Pricing
C# Academy · Lekcja

yield break i wcześniejsze zakończenie

Warunkowo zatrzymuj iterację.

yield break i wcześniejsze zakończenie to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 2 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.

Wczesne zatrzymywanie iteratora

Czasami iterator powinien przestać generować wartości przed osiągnięciem naturalnego końca. Instrukcja yield break natychmiast kończy sekwencję, podobnie jak return w metodach iteratorów.

Podstawy yield break

yield break kończy iterator. Nie są generowane dalsze wartości, a pętla foreach, która pobiera elementy z sekwencji, kończy się.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> UpToFive()
    {
        for (int i = 1; i <= 100; i++)
        {
            if (i > 5) yield break;
            yield return i;
        }
    }

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

Pobieranie, dopóki warunek jest spełniony

Typowym wzorcem jest zwracanie elementów tylko wtedy, gdy warunek jest prawdziwy, a następnie zatrzymanie iteratora. yield break pozwala zrobić to w przejrzysty sposób.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> WhileSmall(IEnumerable<int> nums)
    {
        foreach (var n in nums)
        {
            if (n >= 10) yield break;
            yield return n;
        }
    }

    public static void Main()
    {
        foreach (var n in WhileSmall(new[] { 2, 4, 8, 12, 3 }))
            Console.WriteLine(n);
    }
}

Klauzule ochronne z yield break

Instrukcji yield break można użyć na początku iteratora jako warunku ochronnego. Jeśli dane wejściowe są puste lub nieprawidłowe, iterator nie zwróci żadnych elementów.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    static IEnumerable<string> Lines(string text)
    {
        if (string.IsNullOrEmpty(text)) yield break;
        foreach (var line in text.Split('\n'))
            yield return line;
    }

    public static void Main()
    {
        foreach (var l in Lines("a\nb\nc"))
            Console.WriteLine(l);
        Console.WriteLine("empty count: " + Lines("").Count());
    }
}

Ograniczanie liczby wyników

Licznik w połączeniu z yield break pozwala ograniczyć liczbę elementów generowanych przez iterator, nawet w przypadku długiego źródła.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Take(IEnumerable<int> source, int max)
    {
        int count = 0;
        foreach (var item in source)
        {
            if (count++ >= max) yield break;
            yield return item;
        }
    }

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

break wywołującego a yield break

Sekwencja może zakończyć się na dwa sposoby. Wywołujący może przerwać pobieranie za pomocą break, a iterator może przerwać generowanie za pomocą yield break. W obu przypadkach pętla się kończy, ale z innego powodu.

using System;
using System.Collections.Generic;

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

    public static void Main()
    {
        // Caller decides to stop with break
        foreach (var n in Counting())
        {
            if (n > 3) break;
            Console.WriteLine(n);
        }
    }
}

yield break kończy tylko bieżący iterator

yield break kończy metodę iteratora, w której występuje, a nie zewnętrzną pętlę u wywołującego. Sterowanie wraca do kodu, który wykonywał iterowanie.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Bounded(IEnumerable<int> nums, int limit)
    {
        foreach (var n in nums)
        {
            if (n > limit) yield break; // ends Bounded only
            yield return n;
        }
    }

    public static void Main()
    {
        var result = Bounded(new[] { 1, 2, 9, 3 }, 5);
        Console.WriteLine("iterator created, still running");
        foreach (var n in result) Console.WriteLine(n);
    }
}

Brak yield return po yield break

Po wykonaniu yield break iterator jest zakończony. Żaden kod znajdujący się fizycznie za tą instrukcją na tej samej ścieżce wykonania nie zostanie osiągnięty podczas generowania wartości.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Demo(bool stopEarly)
    {
        yield return 1;
        if (stopEarly) yield break;
        yield return 2;
        yield return 3;
    }

    public static void Main()
    {
        Console.WriteLine("stopEarly = true:");
        foreach (var n in Demo(true)) Console.WriteLine(n);
        Console.WriteLine("stopEarly = false:");
        foreach (var n in Demo(false)) Console.WriteLine(n);
    }
}

Łączenie filtrowania z wczesnym zatrzymaniem

W jednym iteratorze można jednocześnie filtrować i kończyć generowanie: pomijać niektóre wartości, zwracać inne i całkowicie kończyć działanie po napotkaniu wartości sygnalizacyjnej.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> UntilZero(IEnumerable<int> nums)
    {
        foreach (var n in nums)
        {
            if (n == 0) yield break;     // stop at sentinel
            if (n < 0) continue;         // skip negatives
            yield return n;
        }
    }

    public static void Main()
    {
        foreach (var n in UntilZero(new[] { 3, -1, 5, 0, 9 }))
            Console.WriteLine(n);
    }
}

yield break i bloki finally

Jeśli iterator zawiera blok try/finally, blok finally nadal zostanie wykonany, gdy yield break zakończy sekwencję. Gwarantuje to wykonanie czynności porządkowych, takich jak zamknięcie zasobów.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> WithCleanup()
    {
        try
        {
            yield return 1;
            yield break;
        }
        finally
        {
            Console.WriteLine("cleanup ran");
        }
    }

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

Proszę spróbować samodzielnie

Proszę połączyć filtrowanie z wcześniejszym zakończeniem: generować dodatnie liczby, ale całkowicie przerwać, gdy ich suma narastająca przekroczy określony limit.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> WithinBudget(IEnumerable<int> nums, int budget)
    {
        int spent = 0;
        foreach (var n in nums)
        {
            if (n <= 0) continue;
            if (spent + n > budget) yield break;
            spent += n;
            yield return n;
        }
    }

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

Szybkie sprawdzenie

Proszę przypomnieć sobie rolę yield break.

Podsumowanie

yield break kończy iterator przed czasem.

  • Działa jak pozbawiona wartości instrukcja return dla iteratorów.
  • Należy go używać w logice take-while, warunkach ochronnych i limitach liczby elementów.
  • Kończy tylko iterator, a nie pętlę wywołującego.
  • Bloki finally nadal są wykonywane, zapewniając posprzątanie zasobów.

Często zadawane pytania

Czy lekcja „yield break i wcześniejsze zakończenie” jest bezpłatna?

Tak — pełny tekst „yield break i wcześniejsze zakończenie” 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 „yield break i wcześniejsze zakończenie”?

Warunkowo zatrzymuj iterację. Ć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 2 z 4.

Ile czasu zajmuje lekcja „yield break i wcześniejsze zakończenie”?

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