yield 关键字向编译器指示它所在的方法是迭代器块。 编译器生成一个类来实现迭代器块中表示的行为。 在迭代器块中,yield 关键字与 return 关键字结合使用,向枚举器对象提供值。 这是一个返回值,例如,在 foreach 语句的每一次循环中返回的值。 yield 关键字也可与 break 结合使用,表示迭代结束。 有关迭代器的更多信息,请参见迭代器(C# 编程指南)。 下面的示例演示两种形式的 yield 语句。html
yield return <expression>;
yield break;
在 yield return 语句中,将计算 expression 并将结果以值的形式返回给枚举器对象;expression 必须能够隐式转换为 yield 类型的迭代器。express
在 yield break 语句中,控制权将无条件地返回给迭代器的调用方,该调用方为枚举器对象的 IEnumerator.MoveNext 方法(或其对应的泛型 System.Collections.Generic.IEnumerable<T>)或 Dispose 方法。编程
yield 语句只能出如今 iterator 块中,这种块可做为方法、运算符或访问器的主体实现。 这类方法、运算符或访问器的体受如下约束的控制:安全
-
不容许不安全块。app
-
方法、运算符或访问器的参数不能是 ref 或 out。ide
-
yield return 语句不能放在 try-catch 块中的任何位置。 该语句可放在后跟 finally 块的 try 块中。函数
-
yield break 语句可放在 try 块或 catch 块中,但不能放在 finally 块中。oop
yield 语句不能出如今匿名方法中。 有关更多信息,请参见 匿名方法(C# 编程指南)。post
当和 expression 一块儿使用时,yield return 语句不能出如今 catch 块中或含有一个或多个 catch 子句的 try 块中。 有关更多信息,请参见 异常处理语句(C# 参考)。ui
在下面的示例中,迭代器块(这里是方法 Power(int number, int power))中使用了 yield 语句。 当调用 Power 方法时,它返回一个包含数字幂的可枚举对象。 注意 Power 方法的返回类型是 System.Collections.IEnumerable(一种迭代器接口类型)。
public class List
{
//using System.Collections;
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
/*
Output:
2 4 8 16 32 64 128 256
*/
有关更多信息,请参见 C# 语言规范。C# 语言规范是 C# 语法和用法的权威资料。
C# yield return 用法与解析
本文参考自:http://www.jb51.net/article/54810.htm
当初没有认真理解 yield 这个关键字,如今又遇到了依旧不理解,为了之后再也不为了 yield 困惑,决定好好研究一下 yield 的用法与意义:
yield 从字面上理解有“退位,屈服”的意思,转一下弯就理解成“权限转移”,也就是将控制权交给别人,在这里就是把集合里知足条件(若是没有过滤条件,就是全体)的个体的操做转移给另外一个对象。
class Program { static void Main(string[] args) { foreach (var item in FilterWithoutYield) { Console.WriteLine(item); } Console.ReadKey(); } //申明属性,定义数据来源
public static List<int> Data { get { return new List<int>(){1,2,3,4,5,6,7,8}; } } //申明属性,过滤器(不适用yield)
public static IEnumerable<int> FilterWithoutYield { get { var result = new List<int>(); foreach (var i in Data) { if (i > 4) result.Add(i); } return result; } } }
能够看到若是不用yield,要返回大于4的全部的数,就要到另外一个集合。而用yield的状况下就没必要如此麻烦了:
//申明属性,过滤器(使用yield)
public static IEnumerable<int> FilterWithoutYield { get { foreach (var i in Data) { if (i > 4) yield return i; } } }
为何会这样呢?
经过单步调试发现:
虽然2种方法的输出结果是同样的,但运做过程迥然不一样。第一种方法,是把结果集所有加载到内存中再遍历;第二种方法,客户端每调用一次,yield return就返回一个值给客户端,是"按需供给"。
第一种方法,客户端调用过程大体为:

使用yield return,客户端调用过程大体为:

使用yield return为何能保证每次循环遍历的时候从前一次中止的地方开始执行呢?
--由于,编译器会生成一个状态机来维护迭代器的状态。
简单地说,当但愿获取一个IEnumerable<T>类型的集合,而不想把数据一次性加载到内存,就能够考虑使用yield return实现"按需供给"。
============================================================================================
yield是C#为了简化遍历操做实现的语法糖,咱们知道若是要要某个类型支持遍历就必需要实现系统接口IEnumerable,这个接口后续实现比较繁琐要写一大堆代码才能支持真正的遍历功能。举例说明
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
namespace
{
class Program
{
static void Main(string[] args)
{
HelloCollection helloCollection = new HelloCollection();
foreach (string s in helloCollection)
{
Console.WriteLine(s);
}
Console.ReadKey();
}
}
//
public class HelloCollection : IEnumerable
//
{
//
public IEnumerator GetEnumerator()
//
{
//
yield return "Hello";
//
yield return "World";
//
}
//}
public class HelloCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
Enumerator enumerator = new Enumerator(0);
return enumerator;
}
public class Enumerator : IEnumerator, IDisposable
{
private int state;
private object current;
public Enumerator(int state)
{
this.state = state;
}
public bool MoveNext()
{
switch (state)
{
case 0:
current = "Hello";
state = 1;
return true;
case 1:
current = "World";
state = 2;
return true;
case 2:
break;
}
return false;
}
public void Reset()
{
throw new NotSupportedException();
}
public object Current
{
get { return current; }
}
public void Dispose()
{
}
}
}
}
上面注释的部分引用了"yield return”,其功能至关于下面全部代码!能够看到若是不适用yield须要些不少代码来支持遍历操做。
yield return 表示在迭代中下一个迭代时返回的数据,除此以外还有yield break, 其表示跳出迭代,为了理解两者的区别咱们看下面的例子
class A : IEnumerable
{
private int[] array = new int[10];
public IEnumerator GetEnumerator()
{
for (int i = 0; i < 10; i++)
{
yield return array[i];
}
}
}
若是你只想让用户访问ARRAY的前8个数据,则可作以下修改.这时将会用到yield break,修改函数以下
public IEnumerator GetEnumerator()
{
for (int i = 0; i < 10; i++)
{
if (i < 8)
{
yield return array[i];
}
else
{
yield break;
}
}
}
这样,则只会返回前8个数据.
出处:http://www.cnblogs.com/kingcat/archive/2012/07/11/2585943.html
static void Main(string[] args)
{
// Display the even numbers.
Console.WriteLine("Even numbers");
foreach (int i in GetEven())
Console.WriteLine(i);
Console.WriteLine("===================");
// Display the odd numbers.
Console.WriteLine("Odd numbers");
foreach (int i in GetOdd())
Console.WriteLine(i);
//aa();
//kk();
Console.ReadKey();
}
public static int[] ints = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377 };
public static IEnumerable<int> GetEven()
{
foreach (var item in ints)
if (item % 2 == 0)
yield return item;
}
public static IEnumerable<int> GetOdd()
{
foreach (var item in ints)
if (item % 2 == 1)
yield return item;
}