您的位置:首页 > 其它

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

2012-02-19 00:05 281 查看
上一篇文章讲到了如何构建自己的可枚举类型和枚举数!
  这一片将重点讲解我们经常使用的数组,首先抛出一个疑问,为什么定义的数组可以进行foreach遍历?带着这个问题我们来一探究竟!

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

    ①首先看一个简单的列子

     string[] strArray = {"aa","bb","cc","dd"};

     foreach(string item in strArray)

     {

      Console.WriteLine(item);

     } 

    根据上一篇的知识,要想实现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工具进行查看和学习!

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

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

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

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

  

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

    

    


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

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

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

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

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

    

   下一篇:迭代器学习之三:IEnumerable和IEnumerator的泛型结构
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: