• C#基础知识---迭代器与Foreach语句


    一、Foreach语句简介

    在C# 1.0中我们经常使用foreach来遍历一个集合中的元素,然而如果一个集合要支持使用foreach语句来进行遍历,这个集合一般需要IEnumerableIEnumerable<T>接口

    因为foreach是迭代语句,要使用foreach必须要有一个迭代器才行的,而IEnumerable接口中的IEnumerator GetEnumerator()方法是返回迭代器的。

    在C# 1.0中,要获得迭代器一般需要实现IEnumerable接口中的GetEnumerator()方法,然而要实现一个迭代器就必须实现IEnumerator接口。

    在C# 2.0中,提供 yield关键字来简化迭代器的实现。

    foreach被编译后会调用GetEnumerator来返回一个迭代器。

    二、C#1.0中实现迭代器

      1 using System;
      2 using System.Collections;
      3 
      4 namespace 迭代器Demo
      5 {
      6     class Program
      7     {
      8         static void Main(string[] args)
      9         {
     10             Friends friendcollection = new Friends();
     11             foreach (Friend f in friendcollection)
     12             {
     13                 Console.WriteLine(f.Name);
     14             }
     15 
     16             Console.Read();
     17         }
     18     }
     19 
     20     /// <summary>
     21     ///  朋友类
     22     /// </summary>
     23     public class Friend
     24     {
     25         private string name;
     26         public string Name
     27         {
     28             get { return name; }
     29             set { name = value; }
     30         }
     31         public Friend(string name)
     32         {
     33             this.name = name;
     34         }
     35     }
     36 
     37     /// <summary>
     38     ///   朋友集合
     39     /// </summary>
     40     public class Friends : IEnumerable
     41     {
     42         private Friend[] friendarray;
     43 
     44         public Friends()
     45         {
     46             friendarray = new Friend[]
     47             {
     48                 new Friend("张三"),
     49                 new Friend("李四"),
     50                 new Friend("王五")
     51             };
     52         }
     53 
     54         // 索引器
     55         public Friend this[int index]
     56         {
     57             get { return friendarray[index]; }
     58         }
     59 
     60         public int Count
     61         {
     62             get { return friendarray.Length; }
     63         }
     64 
     65         // 实现IEnumerable<T>接口方法
     66        public  IEnumerator GetEnumerator()
     67         {
     68             return new FriendIterator(this);
     69         }
     70     }
     71 
     72     /// <summary>
     73     ///  自定义迭代器,必须实现 IEnumerator接口
     74     /// </summary>
     75     public class FriendIterator : IEnumerator
     76     {
     77         private readonly Friends friends;
     78         private int index;
     79         private Friend current;
     80         internal FriendIterator(Friends friendcollection)
     81         {
     82             this.friends = friendcollection;
     83             index = 0;
     84         }
     85 
     86         #region 实现IEnumerator接口中的方法
     87         public object Current
     88         {
     89             get
     90             {
     91                 return this.current;
     92             }
     93         }
     94 
     95         public bool MoveNext()
     96         {
     97             if (index + 1 > friends.Count)
     98             {
     99                 return false;
    100             }
    101             else
    102             {
    103                 this.current = friends[index];
    104                 index++;
    105                 return true;
    106             }
    107         }
    108 
    109         public void Reset()
    110         {
    111             index = 0;
    112         }
    113 
    114         #endregion 
    115     }
    116 }
    View Code

    三、C#2.0中实现迭代器

     1 namespace 简化迭代器的实现
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             Friends friendcollection = new Friends();
     8             foreach (Friend f in friendcollection)
     9             {
    10                 Console.WriteLine(f.Name);
    11             }
    12 
    13             Console.Read();
    14         }
    15     }
    16 
    17     /// <summary>
    18     ///  朋友类
    19     /// </summary>
    20     public class Friend
    21     {
    22         private string name;
    23         public string Name
    24         {
    25             get { return name; }
    26             set { name = value; }
    27         }
    28         public Friend(string name)
    29         {
    30             this.name = name;
    31         }
    32     }
    33 
    34     /// <summary>
    35     ///   朋友集合
    36     /// </summary>
    37     public class Friends : IEnumerable
    38     {
    39         private Friend[] friendarray;
    40 
    41         public Friends()
    42         {
    43             friendarray = new Friend[]
    44             {
    45                 new Friend("张三"),
    46                 new Friend("李四"),
    47                 new Friend("王五")
    48             };
    49         }
    50 
    51         // 索引器
    52         public Friend this[int index]
    53         {
    54             get { return friendarray[index]; }
    55         }
    56 
    57         public int Count
    58         {
    59             get { return friendarray.Length; }
    60         }
    61 
    62         // C# 2.0中简化迭代器的实现
    63         public IEnumerator GetEnumerator()
    64         {
    65             for (int index = 0; index < friendarray.Length; index++)
    66             {
    67                 // 这样就不需要额外定义一个FriendIterator迭代器来实现IEnumerator
    68                 // 在C# 2.0中只需要使用下面语句就可以实现一个迭代器
    69                 yield return friendarray[index];
    70             }
    71         }
    72     }
    73 }
    View Code

    在上面代码中有一个yield return 语句,这个语句的作用就是告诉编译器GetEnumerator方法不是一个普通的方法,而是实现一个迭代器的方法。

    当编译器看到yield return语句时,编译器知道需要实现一个迭代器,所以编译器生成中间代码时为我们生成了一个实现IEnumerator接口的内部类。

    大家可以通过Reflector工具进行查看,下面是通过Reflector工具得到一张截图:

    四、迭代器执行过程

    注:本文参考http://www.cnblogs.com/zhili/archive/2012/12/02/Interator.html

  • 相关阅读:
    09-2:跳台阶
    09:菲波那切数列
    08:旋转数组的最小值
    07:用两个栈实现队列
    06:重建二叉树
    05:从尾到头打印链表
    04:替换字符
    centos7安装Jenkins更改默认端口并配置Ldap服务器进行用户认证
    Jira配置openLdap服务器进行用户认证
    定时自动从FTP服务器取数据脚本
  • 原文地址:https://www.cnblogs.com/3xiaolonglong/p/9608281.html
Copyright © 2020-2023  润新知