yield关键词是在 C# 2.0 中被引入的,我们都知道实现了 IEnumerable 接口的类都可以用于被 foreach 迭代,这是因为 IEnumerable 接口中提供了一个可迭代的 GetEnumerator() 方法,代码定义如下:
public interface IEnumerable{IEnumerator GetEnumerator();}现在你也可以使用 yield 关键词来指定某些方法也是可以被迭代的,通常 C# 中有两种 yield 的语法格式:yield return <expression> 和 yield break。
为什么要使用 yield 关键词
yield关键词可以实现一种 状态迭代 而不需要提前创建好一个临时集合,换句话说,当你在迭代器中使用 yield return 时,在数据返回之前你不需要创建一个临时集合来存储数据,你可以利用 yield return 一次性返回集合中的每项数据,同时你也可以在方法和get访问器中使用带有迭代的 yield return 语句,值得注意的是,当每次执行 yield return 语句后,控制权都会转交给调用者。
说了这么多,如果有点懵的话,我们来看一个例子,下面的代码展示了如何使用 yield 关键词来返回 Fibonacci 数字,这个方法接收一个int类型的参数。
static IEnumerable<int> GenerateFibonacciNumbers(int n){for (int i = 0, j = 0, k = 1; i < n; i++){yield return j;int temp = j + k;j = k;k = temp;}}上面的代码中 yield return j 在不退出 for 循环的情况下逐个返回斐波那契数,换句话说,这个迭代状态是被保留的,下面的代码展示了如何调用 GenerateFibonacciNumbers()。
foreach (int x in GenerateFibonacciNumbers(10)){Console.WriteLine(x);}下面是仅供参考的完整代码。
class Program{static void Main(string[] args){foreach (int x in GenerateFibonacciNumbers(10)){Console.WriteLine(x);}}static IEnumerable<int> GenerateFibonacciNumbers(int n){for (int i = 0, j = 0, k = 1; i < n; i++){yield return j;int temp = j + k;j = k;k = temp;}}}
也许你注意到了,上面的代码并没有创建一个 list 或者 array 去存放那些输出到控制台的斐波那契额数。
yield 关键词的另一个优点在于可以按需创建和返回你需要的数,下面的代码展示了 Get方法器 中仅返回 1-10 之间的偶数。
public static IEnumerable<int> EvenNumbers{get{for (int i = 1; i <= 10; i++){if ((i % 2) == 0)yield return i;}}}你也可以使用 yield break 来提前中断一个迭代链,如下代码所示:
public IEnumerable<T> GetData<T>(IEnumerable<T> items){if (null == items)yield break;foreach (T item in items)yield return item;}几点原则
当你在用 yield 时,请记住如下几点。
- yield return不能套在- try-catch中,否则会报错。

- yield break不能放在 finally 中。
- yield 方法的返回类型只能是 - IEnumerable, IEnumerable<T>, IEnumerator,IEnumerator<T>。
- 在 yiled 的方法参数中不能使用 ref,out 标记。 
- 不能将 - yield return和- yield break放在匿名方法中。
- 不能将 - yield return和- yield break放在- unsafe方法中。
译文链接:https://www.infoworld.com/article/3122592/my-two-cents-on-the-yield-keyword-in-c.html