迭代器学习之二:数组的可枚举类型和枚举数的定义以及编译器的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来查看:

      迭代器学习之二:数组的可枚举类型和枚举数的定义以及编译器的foreach工作原理

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

 

      c)查看ArrayEnumerator

        迭代器学习之二:数组的可枚举类型和枚举数的定义以及编译器的foreach工作原理

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

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

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

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

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

  

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

    

    迭代器学习之二:数组的可枚举类型和枚举数的定义以及编译器的foreach工作原理

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

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

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

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

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

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

你可能感兴趣的:(foreach)