FOREACH的遍历
在使用FOREACH对集合进行遍历的时候,要求被遍历的对象必须实现了IENUMABLE接口,而该接口的唯一成员方法GETENUMATOR返回实现了IENUMATOR接口的实例对象。
检测IENUMATOR,发现有3个成员,分别是:CURRENT、MOVENEXT、RESET,CURRENT返回当前的成员对象;MOVENEXT把指针向下移动一个位置,如果存在实例成员则返回true,否则返回false,是FOREACH判断循环结束的条件;RESET则重置循环指针。
通过以上分析,想当然的在定义实现了IENUMABLE接口的类时一起实现IENUMATOR接口,也没有发现问题。直到一天需要对自定义的集合连续进行两次FOREACH的时候,发现第一次OK,第二次出现了问题,郁闷呀。调试很久都解决不了问题。
多方面测试、跟踪后,发现FOREACH并不会调用RESET这个重置方法,从而当第二个FOREACH执行的时候,成员指针已经指到最后面,MOVENEXT永远返回false,而之前想当然的认为在调用FOREACH的时候,要么开始执行RESET,要么最后执行RESET,结果不然。
反编译MS对集合类定义的代码,发现,类在实现IENUMABLE的方法GETENUMATOR的时候,是全新的创建了一个实现了IENUMATOR接口内部类实例,所以不会出现连续FOREACH时数据不正常的情况。
MS为什么采用这样的方案实现IENUMATOR呢?想想也是自己蠢呀,如果一个实例集合在多线程中被同时FOREACH,那指针还不混乱?这个实现方案是MS保证集合类实例在多线程环境安全的至要保证。