很多时候我们在使用for循环遍历一个数组的时候,我们都知道可以通过下标的索引找到当前数组中所对应的数据。这只对于简单的数组或集合,如果我们存储的数据不止只有数据项,还有一个标识项,就如同Hashtable 和 Dictionary<key,value> 包含有key value键值对的时候,如果再去使用for循环就没有实际意义了。这种情况下就用到了foreach。有些博客上也有讲解到foreach实现的原理,foreach是被设计用来和可枚举类型一起使用。只要它的遍历对象是可枚举类型。如果一种类型的数据需要使用foreach来遍历数据,那么该类型就必须实现GetEnumerator()方法,具体实现GetEnumerator()可以通过实现IEnumerable接口来创建此方法。当使用foreach语句时,会通过GetEnumerator()方法返回一个枚举迭代器。通过该迭代器可以依次返回集合中项的类对象。从枚举数中请求每一项并且把它作为迭代变量,代码可以读但不可以改。

 IEnuerator接口中通过MoveNext()方法和Current()方法来遍历数据。并返回迭代的数据。

2.使用IEnuerator接口中通过MoveNext()方法和Current()方法写自己的foreach()遍历数据。

   1.首先建一个MyList类,想通过foreach()来遍历列表中的数据:让MyList类实现IEnumerable接口,创建GetEnumerator()方法,调用GetEnumerator()方法返回一个IEnumerator类型的迭代器,用于迭代列表中的数据,并且返回。

class MyList:IEnumerable
      {
            private List<string> _list = new List<string>();

public string this[int index]
             {
                get
                 {
                     return _list[index];
                 }
                set
                 {
                    _list[index] = value;
                 }
             }

public void Add(string value)
           {
                _list.Add(value);
           }

public int Count()
          {
               return _list.Count;
          }

public IEnumerator GetEnumerator()
          {
              return new MyListEnumerator(_list);
          }
     }

2.创建MyListEnumerator类实现IEnumerator 接口,用于遍历数据,并且返回IEnumerator 类型的数据。

class MyListEnumerator : IEnumerator
         {
              private List<string> _list;

public MyListEnumerator(List<string> list)   //构造函数,初始化对象时传递一个list<string>集合
               {
                    _list = list;
               }

private int index = -1;//标识当前数据遍历到第几个位置

public object Current//获得当前对象
             {
                  get
                  {
                      return _list[index];
                  }
             }

public bool MoveNext()//如果还有下一个对象,则移动到下一个对象
            {
                  if (index < _list.Count - 1)
                    {
                         index++;
                         return true;
                    }
                 else
                   {
                        return false;
                   }
            }

public void Reset()//重置指针位置,指向第一个位置
           {
                 index = -1;
           }
     }

通过迭代器把遍历的数据以对象的形式返回给调用方法。

 

MyList myList = new MyList();
          myList.Add("北京");
          myList.Add("上海");
          myList.Add("河南");
          //foreach (string item in myList)
          //{
          // Console.WriteLine(item);
          //}

IEnumerator ator = myList.GetEnumerator();
          while (ator.MoveNext())
          {
             string m = (string)ator.Current;
             Console.WriteLine(m);
          }
          Console.ReadKey();

自我理解foreach工作原理的更多相关文章

  1. Linux内核设计第一周 ——从汇编语言出发理解计算机工作原理

    Linux内核设计第一周 ——从汇编语言出发理解计算机工作原理 作者:宋宸宁(20135315) 一.实验过程 图1 编写songchenning5315.c文件 图2 将c文件汇编成32位机器语言 ...

  2. Linux内核设计(第一周)——从汇编语言出发理解计算机工作原理

    Linux内核设计(第一周)——从汇编语言出发理解计算机工作原理 计算机工作原理 汇编指令 C语言代码汇编分析 by苏正生 原创作品转载请注明出处 <Linux内核分析>MOOC课程htt ...

  3. 通过一个小故事,理解 HTTPS 工作原理

    本文摘录参考: 细说 CA 和证书(主要讲解 CA 的使用) 数字签名是什么?(简单理解原理) 深入浅出 HTTPS 工作原理(深入理解原理) HTTP 协议由于是明文传送,所以存在三大风险: 1.被 ...

  4. 理解 HTTPS 工作原理(公钥、私钥、签名、数字证书、加密、认证)(转)

    本文摘录参考: 细说 CA 和证书(主要讲解 CA 的使用) 数字签名是什么?(简单理解原理) 深入浅出 HTTPS 工作原理(深入理解原理) HTTP 协议由于是明文传送,所以存在三大风险: 1.被 ...

  5. yum服务器搭建(深入理解yum工作原理)

    作者:firefoxbug 时间:July 27, 2014 分类:Linux 前言 在前面一篇rpm包制作描述了rpm的打包过程,这篇文章主要讲述yum的工作原理. yum 运行原理 yum的工作需 ...

  6. 深入理解yum工作原理

    前言 在前面一篇rpm包制作描述了rpm的打包过程,这篇文章主要讲述yum的工作原理. yum 运行原理 yum的工作需要两部分来合作,一部分是yum服务器,还有就是client的yum工具.下面分别 ...

  7. 理解Tomcat工作原理

    WEB服务器 只要Web上的Server都叫Web Server,但是大家分工不同,解决的问题也不同,所以根据Web Server提供的功能,每个Web Server的名字也会不一样. 按功能分类,W ...

  8. 深入理解Cache工作原理

    内容来源:https://zhuanlan.zhihu.com/p/435031232 内容来源:https://zhuanlan.zhihu.com/p/102293437 本文主要内容如下,基本涉 ...

  9. 理解channel 工作原理以及源码

    Go 的并发特性  goroutines: 独立执行每个任务,并可能并行执行 channels: 用于 goroutines 之间的通讯.同步 一个简单的事务处理的例子  对于下面这样的非并发的程序: ...

随机推荐

  1. 【HDU3487】【splay分裂合并】Play with Chain

    Problem Description YaoYao is fond of playing his chains. He has a chain containing n diamonds on it ...

  2. js 实现tab选项卡

    最近一直在研究js  如果不及时复习的话前边学到的东西很快就会忘掉,所以把前段时间的一个简单的tab选项卡的思路写出来也算复习了一下吧, 第一步:先把布局写出来: <div id="d ...

  3. ThinkPHP框架下,jq实现在div中添加标签并且div的大小会随之变化

    php初学者,有什么不对的还请指正. 首先是在html页面中用jq实现添加标签:divAchivePersonnal是select所在的div的外层div,divselectAchivePersonn ...

  4. MySql数据库3【优化1】表的优化

    一.表结构的优化 1.标准化  标准化是在数据库中组织数据的过程.其中包括,根据设计规则创建表并在这些表间建立关系:通过取消冗余度与不一致相关性,该设计规则可以同时保护数据并提高数据的灵活性.通常数据 ...

  5. xgboost中如何自定义metric(python中)

    正好在参加携程的比赛,用的xgboost的算法,但携程比赛的测评函数比较奇怪,不是传统的那些,而是取precision≥0.97的情况下,recall的最大值.那无疑这个测评函数是要自己写的(官方没给 ...

  6. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

  7. 用汇编语言研究C语言的全局变量、局部变量、参数、返回值放在哪里

    前提知识 c0s调用main函数的地址: 11ah main函数的连接地址: 01fah 一.全局变量与局部变量 测试程序 int a1,a2,a3; void f(void); void g(voi ...

  8. Asp.Net Mvc - 在OnResultExecut* 拦截Action返回的HTML

    在Asp.Net MVC项目中通过重写ActionFilterAttribute中的方法,我们就可以在轻松的在Action方法执行前后做一些特殊的操作如:[身份认证.日志记录.内容截取等]. 但是我们 ...

  9. JSP语法

    第3章  JSP语法 [本章专家知识导学] JSP是建立在Java语言基础上的一种Web程序设计语言,具有自己特有的用法和指令.本章首先介绍JSP页面的程序结构,然后讲述JSP程序中经常用到基本的面向 ...

  10. KVO/KVC总结

    KVO/KVC总结       下面是根据网上文章的总结,方便查看. 在网上看别人的文章,了解KVC.KVO,有个kvo-kvc的例子,就是改变数组的内容(插入和删除),同步改变tableview中的 ...