zoukankan      html  css  js  c++  java
  • 迭代器学习之二:数组的可枚举类型和枚举数的定义以及编译器的foreach工作原理

      上一篇文章讲到了如何构建自己的可枚举类型和枚举数!

      这一片将重点讲解我们经常使用的数组,首先抛出一个疑问,为什么定义的数组可以进行foreach遍历?带着这个问题我们来一探究竟!

      1、Array的可枚举类型和枚举数的创建

        ①首先看一个简单的列子     

    1      string[] strArray = { "aa", "bb", "cc", "dd" };
    2 foreach (string item in strArray)
    3 {
    4 Console.WriteLine(item);
    5 }

        根据上一篇的知识,要想实现foreach遍历,就必须要实现可枚举类型以及构建自己的枚举数(或者调用其它方法实现枚举数的遍历),也就是实现IEnumerable和IEnumerator两个接口!

        在说明之前插一句话C#中几乎所有的关键字都是对应着.NET一个类(也就是所谓的映射),比如“int”关键字就是对应的“System.Int32”,那么数组对应的是哪个类呢?答案是“Array”,下面就对Array类做一个探讨! 

        ②通过Reflector工具查看Array类

         说实话以前感觉Reflector离我太远,一直搞不清楚它对我有多大的用处,不过现在却改变了看法,因为当你想深入研究时才会知道它的真正作用!

           a)查看Array实现了哪些接口     

           

          通过Reflector很容易看到它实现了哪些接口以及方法,属性,字段的定义以及实现!

         上面很好的说明了Array已经实现了IEnumerabler接口,说明它现在就是个可枚举类型了,那它也一定实现了GetEnumerator方法!

         b)Array的GetEnumerator方法

          还是通过Reflector来查看:

          

          图示中用方框框起来的是这个方法三个重要的部分(返回枚举数),我们关注的应该是return后面返回的那个对象,到现在为止我们还不知道它是干什么用的,不过我们在心理应该有点感觉到了,这个类是不是跟返回的枚举数有关系呢?带着这个问题我们进一步探讨!

          c)查看ArrayEnumerator

            

          点开ArrayEnumerator,会很惊讶的发现这个类实现了IEnumerator接口并实现了它所有的方法,以及定义了一个数组(_indices),起始项(startIndex)以及一些遍历,其它的方法和属性可以自己通过Reflector工具进行查看和学习!

          看到这儿,头脑里面有没有一种豁然开朗的感觉,它的形式跟我们在第一篇讲的内容基本相似,都符合两个特点:

          I, 实现IEnumerable接口,实现GetEnumerator方法,返回IEnumerator类型的枚举数,使定义的类变为可枚举类型!

          II,实现IEnumerator接口操作返回的枚举数对象(其实枚举数本质上就是数组或集合),以至于可以依次返回集合中项的类对象!

          所以说为什么数组或集合可以进行foreach遍历,就是因为微软封装了实现IEnumerator和IEnumerable接口,我们一般看不到,基本的实现步骤和思想就跟上一篇差不多,只是它里面方法,属性中的代码更加的详细而已,有兴趣的可以通入Reflector深入了解!

      

      2、最后通过一张图来展示在进行foreach的时候,编译器的执行步骤是怎么样的?   

        

        

        说明一下:上面Array在调用GetEnumerator方法时返回是的一个“ArrayEnumerator”类型的对象,但是这个方法的返回值类型是IEnumerator,又因为ArrayEnumerator实现了IEnumerator接口才可以这样操作(也就是子类的引用给了父类)!

        一直对“子类的引用给父类”这句话中的“引用”感到很困惑。百思不能其解,不过在这段学习的过程中对它有了一些自己的见解!

        上面提到的引用其实是存储在栈中的引用地址,这个地址指向的是这个对象存放在堆中的数据(这边涉及到一点栈和堆的知识),而“子类的引用给父类”它的含义只是在说明“引用地址”的所有权发生了改变,而真正的数据却没有改变(包括存放的位置)!

        对于上图的解释就这么多!

        希望园子里面的园友多多拍砖,本人新手,需要各位指点一二!    

        下一篇:迭代器学习之三:IEnumerable和IEnumerator的泛型结构 

  • 相关阅读:
    2017 业余程序员的回顾
    而立将近,可有不惑
    谈谈转行
    吃干抹净提上裤子就甩
    Autosizer应用程序窗口控制工具
    AutoCAD2007专业版
    Revit中如何添加水平仰视平面视图
    Revit中绘制带坡度管道
    Revit自定义快递访问工具栏
    Revit利用对正工具快速修改风管对齐方式
  • 原文地址:https://www.cnblogs.com/yangcaogui/p/2275393.html
Copyright © 2011-2022 走看看