yield 語句 - 提供下一個專案
yield
您可以在反覆運算器中使用 語句,在反覆運算序列時提供序列中的下一個值。 yield
語句有下列兩種形式:
yield return
:在反復專案中提供下一個值,如下列範例所示: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
:若要明確發出反復專案的結束訊號,如下列範例所示:Console.WriteLine(string.Join(" ", TakeWhilePositive(new[] { 2, 3, 4, 5, -1, 3, 4}))); // Output: 2 3 4 5 Console.WriteLine(string.Join(" ", TakeWhilePositive(new[] { 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; } } }
當控制項到達反覆運算器的結尾時,反復專案也會完成。
在上述範例中,反覆運算 IEnumerable<T> 器的傳回型別在非泛型案例中 (,請使用 IEnumerable 作為反覆運算器的傳回型別) 。 您也可以使用 IAsyncEnumerable<T> 作為反覆運算器的傳回型別。 這會使反覆運算器非同步。 await foreach
使用 語句逐一查看反覆運算器的結果,如下列範例所示:
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> 或 IEnumerator 也可以是反覆運算器的傳回型別。 當您在下列案例中實 GetEnumerator
作 方法時,這非常有用:
您可以設計實作 IEnumerable<T> 或 IEnumerable 介面的類型。
您可以新增實例或擴充
GetEnumerator
方法,以使用foreach
語句在型別的實例上啟用反復專案,如下列範例所示: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; } }
您無法在下列專案中使用 yield
語句:
反覆運算器執行
反覆運算器的呼叫不會立即執行,如下列範例所示:
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.
如上述範例所示,當您開始逐一查看反覆運算器的結果時,會執行反覆運算器直到到達第一個 yield return
語句為止。 然後,反覆運算器的執行會暫停,而呼叫端會取得第一個反復專案值並加以處理。 在每個後續反復專案上,反覆運算器的執行會在造成先前暫停的語句之後 yield return
繼續執行,並繼續進行直到到達下一個 yield return
語句為止。 當控制項到達反覆運算器或 yield break
語句的結尾時,反復專案就會完成。