1. 在语句中使用 yield 关键字,表示在该关键字所在的方法、运算符或 get 访问器是迭代器。 通过使用 yield 定义迭代器,可在实现自定义集合类型的 IEnumerable 和 IEnumerator 模式时无需其他显式类
2.yield return 用于返回IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>,一次返回一个元素。yield break用于终止循环遍历。
3. 通过 foreach 语句或 LINQ 查询来使用迭代器方法。 foreach 循环的每次迭代都会调用迭代器方法。 迭代器方法运行到 yield return 语句时,会返回一个 expression,并保留当前在代码中的位置。 当下次调用迭代器函数时执行从该位置重新启动。
4. 可以使用 yield break 语句来终止迭代。
5.迭代器的声明必须满足以下要求:
返回类型必须为 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>。
该声明不能有任何 ref 或out参数。
6.不能在具有以下特点的方法中包含 yield return 或 yield break 语句:
匿名方法。
包含不安全的块的方法
7.异常处理:
不能将 yield return 语句置于 try-catch 块中。 可将 yield return 语句置于 try-finally 语句的 try 块中。
yield break 语句可以位于 try 块或 catch 块,但不能位于 finally 块。
如果 foreach 主体(在迭代器方法之外)引发异常,则将执行迭代器方法中的 finally 块。
8.举例:
public static IEnumerable<int> Power1(int number, int exponent)
{
List<int> list = new List<int>();
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
list.Add(result);
}
return list;
}
public static IEnumerable<int> Power2(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
static void Main(string[] args)
{
//IEnumerable<int> list = Power1(2, 8);
<pre name="code" class="csharp"> IEnumerable<int> list = Power2(2, 8);
foreach (int l in list) { Console.WriteLine("{0}",l); } }
虽然2种方法的输出结果是一样的,但运作过程迥然不同。第一种方法,是把结果集全部加载到内存中再遍历;第二种方法,客户端每调用一次,yield return就返回一个值给客户端,是"按需供给"。
当调用power2时,并不立即执行该方法,在foreach循环时,将为list调用MonveNext方法,此时才执行Power2方法,知道下一个yield return语句,yield return语句返回的表达式不仅决定了循环体使用的l变量值,还决定了元素的Current属性值(它是IEnumerable<int>类型)。
使用yield return为什么能保证每次循环遍历的时候从前一次停止的地方开始执行呢?--因为,编译器会生成一个状态机来维护迭代器的状态。
9.总结:当希望获取一个IEnumerable<T>类型的集合,而不想把数据一次性加载到内存,就可以考虑使用yield return实现"按需供给"。