对于yield关键字我们首先看一下msdn的解释:
如果你在语句中使用 yield 关键字,则意味着它在其中出现的方法、运算符或 get 访问器是迭代器。 通过使用 yield 定义迭代器,可在实现自定义集合类型的 IEnumerable 和 IEnumerator 模式时无需其他显式类(保留枚举状态的类,有关示例,请参阅 IEnumerator<T>)。
yield是一个语法糖
看msdn 的解释总是让人感觉生硬难懂。其实yield关键字很好理解。首先我们对于性质有个了解。yield是一个语法糖。既然yield是在C#中的一个语法糖,那么就说明yield是对一种复杂行为的简化,就是将一段代码简化为一种简单的形式,方便我们程序员使用。
那么yield到底是对什么行为的简化。我们首先来看一下yield的使用场景。
还是来看msdn上的例子。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
foreach (int i in Power(2, 8, ""))
{
Console.Write("{0} ", i);
}
Console.ReadKey();
}
public static IEnumerable<int> Power(int number, int exponent, string s)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
yield return 3;
yield return 4;
yield return 5;
}
}
}
</div>
这是msdn上yield的一种使用场景。
我们首先看一下下面的Power方法。该静态方法返回一个IEnumerablel<int>类型的参数。按照我们平常的做法。应该对数据执行一定操作,然后return一个IEnumerablel<int>类型的参数。我们把Power方法改造如下:
public static IEnumerable<int> Power(int number, int exponent, string s)
{
int result = 1;
//接口不能实例化,我们这儿new一个实现了IEnumerable接口的List
IEnumerable<int> example = new List<int>();
for (int i = 0; i < exponent; i++)
{
result = result * number;
(example as List<int>).Add(result);
}
return example;
}
</div>
这是我们平常的思路。但是这样做就有个问题。这儿要new一个List,或者任何实现了IEnumerable接口的类型。这样也太麻烦了吧。要知道IEnumerable是一个常用的返回类型。每次使用都要new一个LIst,或者其他实现了该接口的类型。与其使用其他类型,不如我们自己定制一个实现了IEnumerable接口专门用来返回IEnumerable类型的类型。我们自己定制也很麻烦。所以微软帮我们定制好了。这个类是什么,那就是yield关键字这个语法糖。
语法糖的实现(实现IEnumerable<T>接口的类)
我们来看一下yield的反编译代码。
namespace ConsoleApplication2
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
internal class Program
{
private static void Main(string[] args)
{
IEnumerable<int> enumerable = Power(2, 8);
Console.WriteLine("Begin to iterate the collection.");
foreach (int num in Power(2, 8))
{
Console.Write("{0} ", num);
}
Console.ReadKey();
}
public static IEnumerable<int> Power(int number, int exponent)
{
<Power>d__0 d__ = new <Power>d__0(-2);
d__.<>3__number = number;
d__.<>3__exponent = exponent;
return d__;
}
[CompilerGenerated]
private sealed class <Power>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable
&nb