C#yield return和yield break

晚上好,各位。今天结合书中所讲和MSDN所查,聊下yield关键字,它是我们简化迭代器的关键。

  如果你在语句中使用了yield关键字,则意味着它在其中出现的方法、运算符或get访问器是迭代器,通过使用yield定义迭代器,可在实现自定义集合类型的IEnumerable和IEnumerator模式时无需显示类(保留枚举状态类),使用yield有两种形式,如下

1 yield return 表达式
2 yield break

  先说明一下yield return语句,每一次返回一个元素。通过foreach语句或LINQ查询来使用迭代器方法。foreach循环的每次迭代都会调用迭代器方法,会保存当前返回的状态。

 1 static void Main(string[] args)
2 {
3 foreach (int i in GetValues())
4 {
5 Console.WriteLine(i);
6 }
7 Console.ReadKey();
8 }
9
10 static IEnumerable<int> GetValues()
11 {
12 yield return 1;
13 yield return 2;
14 yield return 3;
15 }

  不能将yield return语句放在try-catch之中,但可以把它放在try-finally之中。yield return有两个特点:1.返回类型必须是IEnumerable、IEnumerator、IEnumerator<T>、IEnumerable<T>.2.不能使用ref和out修饰符。在匿名方法和不安全代码中不能包含yield return和yield break。下面我们使用yield return来简化上一篇中对Student的迭代,重新个性了Queue<T>这个泛型类,如下

 1 class Queue<T> : IEnumerable<T> where T : class
2 {
3 public List<T> objects = new List<T>();
4 int startPoint = 0;
5 public Queue(List<T> list)
6 {
7 objects = list;
8 }
9
10 //实现从IEnumerable中的GetEnumerator方法
11 /*
12 个人觉得这个方法在迭代中只会调用一次,不然每次都返回一个新的QueueIterator<T>对象,位置记录都会重置为-1
13 */
14 public IEnumerator<T> GetEnumerator()
15 {
16 //return new QueueIterator<T>(this);
17 for (int index = 0; index < objects.Count; index++)
18 {
19
20 yield return objects[(index + startPoint) % objects.Count];
21 }
22 }
23
24 IEnumerator IEnumerable.GetEnumerator()
25 {
26 throw new NotImplementedException();
27 }
28 }

  代码到了yield return时,返回objects中一个合适的元素,并保存当前的状态,等下一次调用时从记数的位置开始。在使用程序中,如下,和原先一样。

 1 List<Student> list = new List<Student> {
2 new Student("СA"),
3 new Student("СB"),
4 new Student("СC"),
5 new Student("СD"),
6 new Student("СE")
7 };
8 ConsoleDemo.Chapter6.Queue<Student> lq = new Chapter6.Queue<Student>(list);
9
10 foreach (var obj in lq)
11 {
12 obj.SayName();
13 }

  可以看到结果都是迭代的打印每一个元素的名字。在来说下return break,从break中可以看中,是跳出,那意思就应该上跳出迭代,如

 1 class Program
2 {
3 static void Main(string[] args)
4 {
5
6 foreach (int i in GetValues())
7 {
8 Console.WriteLine(i);
9 }
10 Console.ReadKey();
11 }
12
13 static IEnumerable<int> GetValues()
14 {
15 yield return 1;
16 yield return 2;
17 yield break;
18 yield return 3;
19 }
20 }

  到了yield return 2时,下一语句是yield break,则在控制台只会打印1,2,因为在打印3之前就使用yield break跳出迭代了。

  下面我们使用一个实际点的读文件的例子。新建一个文本demo.txt,内容如下

 1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 0

  代码如下

 1 class Program
2 {
3 static void Main(string[] args)
4 {
5 foreach(var line in ReadLines("./demo.txt"))
6 {
7 Console.WriteLine(line);
8 }
9 Console.ReadKey();
10 }
11
12 static IEnumerable<string> ReadLines(string path)
13 {
14 string line;
15 TextReader tr = File.OpenText(path);
16 while ((line = tr.ReadLine()) != null)
17 {
18 yield return line;
19 }
20 }
21 }

  当然其实File中的表态方法是有ReadLines方法的,返回的也是IEnumerable<string>,看来我们是多此一举了,不过也不错,知道了一些yield的使用,原理的那些真心不敢写,写了自己也看不懂,希望以后能用自己组织语言,解译那些原理。

  请斧正。

 

C#yield return和yield break的更多相关文章

  1. 12.C#yield return和yield break及实际应用小例(六章6.2-6.4)

    晚上好,各位.今天结合书中所讲和MSDN所查,聊下yield关键字,它是我们简化迭代器的关键. 如果你在语句中使用了yield关键字,则意味着它在其中出现的方法.运算符或get访问器是迭代器,通过使用 ...

  2. yield return 和 yield break

    //yield return 返回类型必须为 IEnumerable.IEnumerable<T>.IEnumerator 或 IEnumerator<T>. static I ...

  3. yield return 和yield break

    这个还是有点意思,两个都是有返回的意思,但是区别在哪里呢? 1.return 会销毁函数的局部变量,下次调用的时候又会产生新的值 2.yield 当退出函数的时候,变量人然存在,函数下次调用的时候变量 ...

  4. C# yield return 和 yield break

    yield关键字用于遍历循环中,yield return用于返回IEnumerable<T>,yield break用于终止循环遍历. 以下对比了使用yield return与不使用yie ...

  5. 读书笔记 C# yield return与yield break执行顺序的浅析

    yield return可一次返回一个元素,并保留当前在代码中的位置,下次调用当前迭代器函数时,将从该位置从新执行.也就是说执行了yield return的时候,迭代器函数就返回了一个元素给forea ...

  6. yield return,yield break

    转自, http://www.cnblogs.com/kingcat/archive/2012/07/11/2585943.html yield return 表示在迭代中下一个迭代时返回的数据,除此 ...

  7. 可惜Java中没有yield return

    项目中一个消息推送需求,推送的用户数几百万,用户清单很简单就是一个txt文件,是由hadoop计算出来的.格式大概如下: uid caller 123456 12345678901 789101 12 ...

  8. yield return的用法简介

    使用yield return 语句可一次返回一个元素. 迭代器的声明必须满足以下要求: 返回类型必须为 IEnumerable.IEnumerable<T>.IEnumerator 或 I ...

  9. C#中yield return用法分析

    这篇文章主要介绍了C#中yield return用法,对比使用yield return与不使用yield return的流程,更直观的分析了yield return的用法,需要的朋友可以参考下. 本文 ...

随机推荐

  1. hdoj 2063 过山车 【双边匹配匈牙利算法】

    过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  2. HDU 3032 Nim or not Nim? (需求的游戏SG功能)

    意甲冠军:经典Nim游戏转换,给你n礧pi,每个堆栈有pi石头, Alice和Bob轮流石头,意一堆中拿走随意个石子,也能够将某一堆石子分成两个小堆 (每堆石子个数必须不能为0).先拿完者获胜 思路: ...

  3. 第一pga 畸形消费分析

     第一pga 畸形消费分析 os: aix 6 db:10205 ------使用os 命令观察oracle 存消耗情况 #ps gv ......                         ...

  4. Linux以下银行乱码

    更改 /etc/sysconfig/i18n 档,例如 LANG="en_US.UTF-8",xwindow它会显示英文界面. LANG="zh_CN.GB18030&q ...

  5. cocos2dx --- button点击放大中心

    自定义简单button,直接附着到代码: MenuItem* MenuItemNode::create( const char* normal,Ref* target,SEL_MenuHandler ...

  6. vs2013提交github代码

    vs2013的新特性之一就是可以方便的通过集成的git工具管理git代码.今天简单给大家演示 在github新建仓库 复制仓库地址 克隆仓库到本地(这一步非常重要,只有顺利获取github的code, ...

  7. 章节2:SQL之多表连接

    原文:章节2:SQL之多表连接 Sql的多表连接关系有:内连接.外连接和交叉连接. 先建立两个用于演示的表: TB_Characters: Id Character 1 内向 2 外向 3 中性性格 ...

  8. svn常见错误汇总

    comment中的换行.把换行去掉就可以了

  9. DirectX 11游戏编程学习笔记2: 文章1章Vector Algebra(向量代数)

    本文由哈里_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com         注:我给的电子版是700多页.而实体书是800多页,所以我在提到相关概念的时候.会使用章节号而 ...

  10. Nagios显示器MySQL一个错误:NRPE: Unable to read output具体的解决过程

    前言:nagios介面.见监测mysql服务错误,如下面: Warning:NRPE: Unable to read output 1,跟nagios显示器server上check下 1.1.运行ch ...