先来看一段代码:
相信懂点代码的人都基本上都能看懂,首先看看List都继承了哪些类,转到定义:
其中我们关键要看的就是IEnumerable这个类,然后再转到定义:
发现里面有一个GetEnumberator的成员,这个成员是一个迭代器,然后我们来看看这个迭代器:
这里面有三个成员:Current表示返回当前的值,MoveNext表示指针指向下一个,Reset表示重置指针。
好了,看了这些,基本上大概了解了List,那么foreach具体是怎么来实现对List进行访问的呢?
那好,我们先来设置一个断点,一步一步看看foreach是怎么运行的:
我们把程序跑起来:
然后我们往下走
然后再往下走:
运行到了array这里,这里发生了什么,一会再解释,然后再往下:
运行到了in,然后再往下看:
下面的我相信你都猜到了:
但是运行到这里下一次会去哪里运行呢?是array还是in或者是var item?
我们执行下一步发现到了in这一步,为什么呢?这中间发生了什么?
详解:
也许你经常用foreach,但是看完上面的流程,估计你会有一点兴趣往下看,首先看到的是运行到foreach,然后就是array,其实执行到array的时候是把List整个集合复制了一个副本放到内存里面,和集合本身存放的位置不一样,这就是为什么foreach不能改变原始的数据。接着执行到in,其实这里执行了迭代器中的两个方法,首先是前面提到的MoveNext方法,把当前的指针指向下一个地址,然后执行Current方法,返回当前地址的值。然后执行var item,in之后就把这个值赋给item,然后执行后面的操作,而下一次就不用执行array了,直接执行in,这就是我们看到的为什么第一次迭代完了之后执行的是in。由于List还继承了IEnumerable<T>这个类,所以我们在迭代的时候可以不用进行数据类型的转换,这也就是为什么foreach比使用自身的迭代器要快,而且访问的时候是通过指针访问,众所周知,指针的访问速度是很快的。
2015年8月18日18:08:04
By:champly
版权声明:本文为博主原创文章,未经博主允许不得转载。