C# 迭代器中yield关键字的使用

古城微笑少年丶 2023-06-23 09:56 5阅读 0赞

上一篇笔记:C# 迭代器 https://blog.csdn.net/dayuhaitang1/article/details/103593599
在上一篇笔记中,演示的是C#1.0中的迭代器的创建方法,而在C#2.0中经过了改进之后又有了新的书写形式,所以写一篇笔记记录一下。

一、yield关键字

C#2.0中的迭代器的实现代码相较于C#1.0有了很大幅度的减少,之所以会这样这主要就是引入了yield关键字。yield关键字其实质就是在编译器对代码进行编译时,遇到yield关键字时就是在提示编译器这是实现一个迭代器块的方法。也就是将本来应该由我们创建嵌套类实现IEnumerator的工作,让编译器帮我们做了而已。但是这样的确使我们为实现迭代器减少了很大的工作量,使我们能更好的运用迭代器这一工具。

二、利用yield实现迭代器

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. object[] values = { "a", "b", "c", "d", "e" };
  6. IterationSample collection = new IterationSample(values, 3);
  7. foreach (var item in collection)
  8. {
  9. Console.WriteLine(item);
  10. }
  11. Console.ReadKey();
  12. }
  13. }
  14. //迭代器实现
  15. public class IterationSample : IEnumerable
  16. {
  17. object[] values;
  18. int startingPoint;
  19. public IterationSample(object[] values, int startingPoint)
  20. {
  21. this.values = values;
  22. this.startingPoint = startingPoint;
  23. }
  24. //得到一个迭代器
  25. public IEnumerator GetEnumerator()
  26. {
  27. //利用yield关键字实现迭代器
  28. for (int i = 0; i < values.Length; i++)
  29. {
  30. yield return values[(i + startingPoint) % values.Length];
  31. }
  32. }
  33. }

实现的效果如下:
在这里插入图片描述
从上很容易可以看出,C#2.0利用yield关键字实现迭代器而编写的代码量相较于C#1.0而言,得到了大幅度的减少,仅仅只用了4行代码就实现了C#1.0中几十行代码才能做到的事情。但是真实的情况是什么呢?我们将其放入反编译器中再来看一下,如下所示:
在这里插入图片描述在这里插入图片描述

我们会很容易发现,其实想比较C#1.0而言,我们只不过是把我们应该做的事情推给了编译器罢了,一样是嵌套类,一样是MoveNext()、Reset()和Current等等,只不过是名字变成了随机的名字,但是该有的代码(代码有所不同)并没有任何的减少(在编译器中)。但是从这我们也可以看出yield的好处,这的确只需要这一个关键字就可以实现以前需要几十行代码的迭代器功能。

三、yield return和yield break

yield关键字不仅只是减少了实现迭代器的代码量,他也增加了可读性,给人一种好像是直接访问了私有数据成员values所包含的数据,并把它作为返回值传递出去。但是C#2.0中不仅拥有yield return,还有更为神奇的yield break,我们稍微改变一下上面的代码来看看yield break的作用是什么?如下所示:

  1. //得到一个迭代器
  2. public IEnumerator GetEnumerator()
  3. {
  4. for (int i = 0; i < values.Length; i++)
  5. {
  6. yield return values[(i + startingPoint) % values.Length];
  7. yield break; //变化之处
  8. }
  9. }

运行结果如下:
在这里插入图片描述
你会发现只输出了一个字符,迭代块中yield break的作用(结束迭代)就有点像普通方法中的return的作用,所以这也就引出了迭代块中的一个注意事项:在迭代块中不能使用return语句,这是因为迭代块中已经有了相同功能的yield break。

四、小结

说了这么多,总结了下面的几点:1、迭代器中的MoveNext()方法是最先被调用的,然后才会调用迭代器中的Current属性。2、yield return并不会停止代码的运行,他只是返回类中的数据而已。3、yield break才会终止程序的运行,相当于普通方法中的return语句。4、yield关键字只是让我们本应做的工作(代码)推给了编译器,编译之后的代码其实并没有减少。以我目前的理解,我只能想到yield的这些方面,可能理解的还不够全面,仍待日后进一步的了解,努力看书吧。

注:本文参考了《C# In Depth》这本书,推荐大家想要深入了解C#可以看看这本书

发表评论

表情:
评论列表 (有 0 条评论,5人围观)

还没有评论,来说两句吧...

相关阅读