Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Du använder -instruktionen yield i en iterator för att ange nästa värde eller signalera slutet på en iteration. -instruktionen yield har följande två formulär:
- yield return: för att ange nästa värde i iterationen, som följande exempel visar:- foreach (int i in ProduceEvenNumbers(9)) { Console.Write(i); Console.Write(" "); } // Output: 0 2 4 6 8 IEnumerable<int> ProduceEvenNumbers(int upto) { for (int i = 0; i <= upto; i += 2) { yield return i; } }
- yield break: för att uttryckligen signalera slutet på iterationen, som följande exempel visar:- Console.WriteLine(string.Join(" ", TakeWhilePositive(new int[] {2, 3, 4, 5, -1, 3, 4}))); // Output: 2 3 4 5 Console.WriteLine(string.Join(" ", TakeWhilePositive(new int[] {9, 8, 7}))); // Output: 9 8 7 IEnumerable<int> TakeWhilePositive(IEnumerable<int> numbers) { foreach (int n in numbers) { if (n > 0) { yield return n; } else { yield break; } } }- Iterationen avslutas också när kontrollen når slutet av en iterator. 
I föregående exempel är IEnumerable<T> returtypen av iteratorer (i icke-generiska fall används IEnumerable som returtyp för en iterator). Du kan också använda IAsyncEnumerable<T> som returtyp för en iterator. Det gör en iterator asynkron. Använd -instruktionen await foreach för att iterera över iteratorns resultat, som följande exempel visar:
await foreach (int n in GenerateNumbersAsync(5))
{
    Console.Write(n);
    Console.Write(" ");
}
// Output: 0 2 4 6 8
async IAsyncEnumerable<int> GenerateNumbersAsync(int count)
{
    for (int i = 0; i < count; i++)
    {
        yield return await ProduceNumberAsync(i);
    }
}
async Task<int> ProduceNumberAsync(int seed)
{
    await Task.Delay(1000);
    return 2 * seed;
}
              IEnumerator<T> eller IEnumerator kan också vara returtypen för en iterator. Använd dessa returtyper när du implementerar GetEnumerator metoden i följande scenarier:
- Du utformar den typ som implementerar IEnumerable<T> eller IEnumerable gränssnitt. 
- Du lägger till en instans- eller för att aktivera iteration över typens instans med -instruktionen - GetEnumerator, som följande exempel visar:- public static void Example() { var point = new Point(1, 2, 3); foreach (int coordinate in point) { Console.Write(coordinate); Console.Write(" "); } // Output: 1 2 3 } public readonly record struct Point(int X, int Y, int Z) { public IEnumerator<int> GetEnumerator() { yield return X; yield return Y; yield return Z; } }
Du kan inte använda -uttrycken yield i:
- metoder med i, ref, eller ut parametrar.
- lambda-uttryck och anonyma metoder.
- 
              osäkra block. Före C# 13 yieldvar ogiltigt i alla metoder med ettunsafeblock. Från och med C# 13 kan du användayieldi metoder medunsafeblock, men inte iunsafeblocket.
- 
              yield returnochyield breakkan inte användas i catch och slutligen block, eller i försök block med ett motsvarandecatchblock. Instruktionenyield returnochyield breakkan användas i etttryblock utancatchblock, bara ettfinallyblock.
              using instruktioner i iteratorer
Du kan använda using instruktioner i iteratormetoder. Eftersom using instruktioner kompileras till try block med finally satser (och inga catch block) fungerar de korrekt med iteratorer. Disponibla resurser hanteras korrekt under iteratorns körning:
Console.WriteLine("=== Using in Iterator Example ===");
// Demonstrate that using statements work correctly in iterators
foreach (string line in ReadLinesFromResource())
{
    Console.WriteLine($"Read: {line}");
    // Simulate processing only first two items
    if (line == "Line 2") break;
}
Console.WriteLine("Iteration stopped early - resource should still be disposed.");
static IEnumerable<string> ReadLinesFromResource()
{
    Console.WriteLine("Opening resource...");
    using var resource = new StringWriter(); // Use StringWriter as a simple IDisposable
    resource.WriteLine("Resource initialized");
    
    // These lines would typically come from the resource (e.g., file, database)
    string[] lines = { "Line 1", "Line 2", "Line 3", "Line 4" };
    
    foreach (string line in lines)
    {
        Console.WriteLine($"About to yield: {line}");
        yield return line;
        Console.WriteLine($"Resumed after yielding: {line}");
    }
    
    Console.WriteLine("Iterator completed - using block will dispose resource.");
}
Som föregående exempel visar förblir resursen som hämtas i -instruktionen using tillgänglig under iteratorns körning, även när iteratorn pausar och återupptar körningen vid yield return -instruktioner. Resursen tas bort när iteratorn slutförs (antingen genom att nå slutet eller via yield break) eller när själva iteratorn tas bort (till exempel när anroparen bryter ut från uppräkningen tidigt).
Körning av en iterator
Anropet av en iterator kör det inte omedelbart, vilket visas i följande exempel:
var numbers = ProduceEvenNumbers(5);
Console.WriteLine("Caller: about to iterate.");
foreach (int i in numbers)
{
    Console.WriteLine($"Caller: {i}");
}
IEnumerable<int> ProduceEvenNumbers(int upto)
{
    Console.WriteLine("Iterator: start.");
    for (int i = 0; i <= upto; i += 2)
    {
        Console.WriteLine($"Iterator: about to yield {i}");
        yield return i;
        Console.WriteLine($"Iterator: yielded {i}");
    }
    Console.WriteLine("Iterator: end.");
}
// Output:
// Caller: about to iterate.
// Iterator: start.
// Iterator: about to yield 0
// Caller: 0
// Iterator: yielded 0
// Iterator: about to yield 2
// Caller: 2
// Iterator: yielded 2
// Iterator: about to yield 4
// Caller: 4
// Iterator: yielded 4
// Iterator: end.
Som föregående exempel visar, när du börjar iterera över en iterators resultat, körs en iterator tills den första yield return instruktionen har nåtts. Sedan pausas körningen av en iterator och anroparen får det första iterationsvärdet och bearbetar det. På varje efterföljande iteration återupptas körningen av en iterator efter -instruktionen yield return som orsakade den tidigare avstängningen och fortsätter tills nästa yield return instruktion har nåtts. Iterationen slutförs när kontrollen når slutet av en iterator eller en yield break -instruktion.
Språkspecifikation för C#
Mer information finns i avsnittet yield statement i C#-språkspecifikationen.