yield 關鍵字在迭代器塊中用於向枚舉器對象提供值或發出迭代結束信號。
先看一下下面的例子:
using System;
using System.Collections;
namespace yieldTest
{
class Program
{
static void Main(string[] args)
{
StringCollection sc = new StringCollection();
foreach (string str in sc)
{
Console.WriteLine(str);
}
Console.ReadLine();
}
}
//public class StringCollection : IEnumerable
//{
// public IEnumerator GetEnumerator()
// {
// yield return "aaa";
// yield return "bbb";
// yield return "ccc";
// yield return "ddd";
// }
//}
public class StringCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
return new Enumerator();
}
class Enumerator : IEnumerator, IDisposable
{
private string current;
public object Current
{
get { return current; }
}
public bool MoveNext()
{
switch (current)
{
case "aaa":
current = "bbb";
return true;
case "bbb":
current = "ccc";
return true;
case "ccc":
current = "ddd";
return true;
case "ddd":
return false;
default:
current = "aaa";
return true;
}
}
public void Reset()
{
throw new NotImplementedException();
}
public void Dispose()
{
}
}
}
}
在這個例子中,註釋掉的內容引用了“yield return”, 其功能完全等同於下面那麼大段代碼。在我們編寫某個支持遍歷的類型時就必須實現接口IEnumerable,這個接口後續實現比較繁瑣要寫一大堆代碼才能支持真正的遍歷功能。yield簡化了遍歷操作的實現語法。它的形式爲下列之一:
yield return <expression>; yield break;
yield 關鍵字與 return 關鍵字結合使用,向枚舉器對象提供值。這是一個返回值,例如,在上面的例子中 foreach 語句的每一次循環中返回的值。這種取得返回值的方式有所不同,即取到一個數據後馬上返回該數據,不需要全部數據裝入數列完畢,這樣有效提高了遍歷效率。例如:
using System;
using System.Collections;
using System.Threading;
namespace yieldTest
{
public class NumberCollection : System.Collections.IEnumerable
{
public System.Collections.IEnumerator GetEnumerator()
{
yield return "1";
Thread.Sleep(5000);
yield return "2";
Thread.Sleep(5000);
yield return "3";
Thread.Sleep(5000);
yield return "4";
Thread.Sleep(5000);
yield return "5";
Thread.Sleep(5000);
yield return "6";
}
}
class program
{
static void Main(string[] args)
{
NumberCollection arrPersons = new NumberCollection();
foreach (string s in arrPersons)
{
System.Console.WriteLine(s);
}
System.Console.ReadLine();
}
}
}
yield 關鍵字也可與 break 結合使用,表示迭代結束。例如:
class program
{
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (true)
{
if (counter > exponent)
yield break;
counter++;
result = result * number;
yield return result;
}
yield return 999;
}
static void Main(string[] args)
{
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
Console.ReadLine();
}
}
其中 yield return 999; 這段代碼是爲了測試 yield break 與普通的break的區別,普通的break只是跳出while循環,這時它還停留在迭代器中;在 yield break 語句中,控制權將無條件地返回給迭代器的調用方,該調用方爲枚舉器對象的 IEnumerator.MoveNext 方法(或其對應的泛型 System.Collections.Generic.IEnumerable<T>)或
Dispose 方法。其他:
yield return <expression>; //在 yield return 語句中,將計算 expression 並將結果以值的形式返回給枚舉器對象;expression 必須可以隱式轉換爲 yield 類型的迭代器。
yield 語句只能出現在 iterator 塊中,這種塊可作爲方法、運算符或訪問器的主體實現。這類方法、運算符或訪問器的體受以下約束的控制:
不允許不安全塊。
方法、運算符或訪問器的參數不能是 ref 或 out。
yield return 語句不能放在 try-catch 塊中的任何位置。該語句可放在後跟 finally 塊的 try 塊中。
yield break 語句可放在 try 塊或 catch 塊中,但不能放在 finally 塊中。
yield 語句不能出現在匿名方法中。
有關更多信息,請參見匿名方法(C# 編程指南)。