• C#yield return和yield break


    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的使用,原理的那些真心不敢写,写了自己也看不懂,希望以后能用自己组织语言,解译那些原理。

      请斧正。

     
  • 相关阅读:
    html和js的编码格式
    如何通过webStorm快速恢复误删除的工程
    模板使用的一个坑
    一个字符串处理的小算法题
    工信部,映射,映射端口,热备,磁盘,虚拟磁盘,冗余,磁盘阵列技术,廉价冗余磁盘阵列 ,RAID 0,RAID1 ,RAID 3,RAID 5,RAID 6 名词解释
    项目管理,REID,矩阵,终端,镜像,Voip,AVB,串口,串口服务器,数据库,数据仓库,码流,心跳包,名词解释
    TCP协议,UDP协议,Utp,双绞线,DHCP协议,子网掩码,LAN,VLAN,网口,服务器,UI设计,Linux系统,Unix系统,名词解释
    IOS,ISO,OSI,交换机,路由器,MAC地址,网卡,网关,DNS,DNS服务器,名词解释
    中控,I/O端口,继电器,红外接口,编码器,解码器,主机,名词解释
    产品需求的讨论收集,整理描述,反馈实现,实施与验收使用,步骤方法与心得
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4200062.html
Copyright © 2020-2023  润新知