yield deyimi - sonraki öğeyi sağlayın
Bir sonraki değeri sağlamak veya yinelemenin sonuna işaret etmek için bir yineleyicide deyimini kullanırsınızyield
. deyimi yield
aşağıdaki iki biçime sahiptir:
yield return
: aşağıdaki örnekte gösterildiği gibi yinelemede bir sonraki değeri sağlamak için: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
: aşağıdaki örnekte gösterildiği gibi yinelemenin sonunu açıkça işaret etmek için: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; } } }
Yineleme, denetim yineleyicinin sonuna ulaştığında da tamamlar.
Yukarıdaki örneklerde, yineleyicilerin dönüş türü şöyledir IEnumerable<T> (yineleyici olmayan durumlarda, yineleyicinin dönüş türü olarak kullanın IEnumerable ). Yineleyicinin dönüş türü olarak da kullanabilirsiniz IAsyncEnumerable<T> . Bu, bir yineleyiciyi zaman uyumsuz yapar. await foreach
Aşağıdaki örnekte gösterildiği gibi yineleyicinin sonucunu yinelemek için deyimini kullanın:
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> veya IEnumerator yineleyicinin dönüş türü de olabilir. Aşağıdaki senaryolarda yöntemini uygularken GetEnumerator
bu dönüş türlerini kullanın:
Veya arabirimini uygulayan türü tasarlarsınız IEnumerable<T> IEnumerable .
Aşağıdaki örnekte gösterildiği gibi deyimiyle
foreach
türün örneği üzerinde yinelemeyi etkinleştirmek için bir örnek veya uzantıGetEnumerator
yöntemi eklersiniz: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; } }
deyimlerini şu şekilde kullanamazsınız yield
:
- in, ref veya out parametrelerine sahip yöntemler
- lambda ifadeleri ve anonim yöntemler
- güvenli olmayan bloklar. C# 13'e geçmeden önce,
yield
bir bloğu olan herhangi birunsafe
yöntemde geçersizdi. C# 13'le başlayarak blokluunsafe
yöntemlerde kullanabilirsinizyield
ancak bloktaunsafe
kullanamazsınız. yield return
veyield break
try, catch ve finally bloklarında kullanılamaz.
Yineleyici yürütme
Aşağıdaki örnekte gösterildiği gibi yineleyici çağrısı hemen yürütülmüyor:
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.
Yukarıdaki örnekte gösterildiği gibi, yineleyicinin sonucunu yinelemeye başladığınızda, ilk yield return
deyime ulaşılana kadar bir yineleyici yürütülür. Ardından, bir yineleyicinin yürütülmesi askıya alınır ve çağıran ilk yineleme değerini alır ve işler. Sonraki her yinelemede, bir yineleyicinin yürütülmesi önceki askıya alma işlemine yield return
neden olan deyimden sonra devam eder ve sonraki yield return
deyime ulaşılana kadar devam eder. Denetim bir yineleyicinin veya yield break
deyimin sonuna ulaştığında yineleme tamamlar.
C# dili belirtimi
Daha fazla bilgi için C# dil belirtiminin ödeme deyimi bölümüne bakın.