yield关键字是微软的一个语法糖,使用它可以让我们的代码具有更高可读性和更好性能。有了yield关键字,当我们需要返回IEnumerable类型的时候,直接yield返回数据就可以了。也不用new一个list,或其他类型。 :::info 如果要通过计算并返回一个集合数据,传统的办法就是建一个IEnumerable集合,然后把计算出来的数据装到这个集合里面再返回。如果这个计算很慢,一秒钟算出一个值,10个值算出来再返回展示给用户,相当于有10秒钟,用户不知道程序在干嘛。而用yield return,每秒钟就能给用户提供一个值。虽然全部完成也要10秒钟,但是体验感不同。 :::
yield语法
yield return <expression>;yield break;
- yield return语句返回集合的一个元素,并移动到下一个元素上
- yield break可以停止迭代,相当于正常代码块的 return 语句(迭代器中直接使用 return 是非法的)
- 包含yield语句的方法或属性是迭代器。迭代器必须满足以下要求:
- 返回类型必须是IEnumerable、IEnumerable
、IEnumerator或 IEnumerator - 它不能有任何ref或out参数
- 返回类型必须是IEnumerable、IEnumerable
- yield return语句不能位于try-catch块。
- yield return语句可以位于try-finally的try块。
yield break语句可以位于try块或catch块,但是不能位于finally块。
例子
static void Main(string[] args){//可用一个变量来装,也可以直接迭代foreach (var item in yield1(100)){Console.WriteLine(item);}Console.ReadLine();}//用法1:每个0.5秒打印返回一个元素static IEnumerable<int> yield1(int n){for(int i = 1; i < n; i++){if (i % 88 == 0){yield break;}if (i % 2 == 0){Thread.Sleep(500);yield return i;}}}//用法2:打印123的时候每隔一秒打印一次static IEnumerable<int> yield2(){Thread.Sleep(1000);yield return 1;Thread.Sleep(1000);yield return 22;Thread.Sleep(1000);yield return 333;yield return 4444;yield return 55555;yield return 666666;}
关于yield的性能比较
static void Main(string[] args){DateTime t1 =DateTime.Now;foreach (var item in listYieldReturn()){//Console.WriteLine(item);}DateTime t2 = DateTime.Now;Console.WriteLine("耗时:"+(t2-t1).TotalMilliseconds);}//耗时1450ms,进程占用内存12MBstatic IEnumerable<string> listYieldReturn(){for (int i = 0; i < 100000000; i++){yield return "这是一段字符串";}}//耗时3250ms,进程占用内存2.1GB//需要把Main方法里面的东西封装到一个返回void的方法里面。Main里面调用这个方法。之后再GC.Collect(GC.MaxGeneration);才能回收掉这2G的垃圾static IEnumerable<string> listReturn(){List<string> list = new List<string>();for(int i = 0; i < 100000000; i++){list.Add("这是一段字符串");}return list;}
