笔记:IEnumerable和IEnumerator(包括泛型版)

本文解释了集合类为何不直接支持IEnumerator接口,而是通过IEnumerable接口实现枚举器以维护循环遍历的状态。通过实现IEnumerator接口,集合类能够支持foreach方式的遍历,并且能够处理多个循环交错遍历同一集合的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1. 一个Collection要支持foreach方式的遍历,必须实现IEnumerable接口(亦即,必须以某种方式返回IEnumerator对象)。 

2. IEnumerator对象具体实现了iterator(通过MoveNext(),Reset(),Current)。 

3. 从这两个接口的用词选择上,也可以看出其不同:IEnumerable是一个声明式的接口,声明实现该接口的class是“可枚举(enumerable)”的,但并没有说明如何实现枚举器(iterator)IEnumerator是一个实现式的接口,IEnumerator对象就是一个iterator(迭代器)。 

4. IEnumerable和IEnumerator通过IEnumerable的GetEnumerator()方法建立了连接,可以通过IEnumerable的GetEnumerator()得到IEnumerator对象。

5. 由于IEnumerable<T>扩展(继承)了旧的IEnumerable接口,所以要实现两个不同的方法:
IEnumerator<T> GetEnumerator();
IEnumerator GetEnumerator(); // 由于和泛型版本的方法同名,所以该方法的实现需要使用显式接口实现

为什么集合类不直接继承(支持)IEnumerator<T>和IEnumerator接口?
      假如同时有两个循环交错遍历同一个集合(一个foreach嵌套了另外一个foreach),那么集合必须维持当前元素的一个状态指示器,确保当调用MoveNext()方法时,能正确定位下一个元素。

      为了解决这个问题,集合类不直接支持IEnumerator<T>和IEnumerator接口。而是通过IEnumerable的GetEnumerator返回一个新的IEnumerator对象来负责维护循环遍历的状态,IEnumerator(迭代器,或者叫枚举数)相当于一个“游标”(cursor)或者“书签”。可以有多个书签,移动每个书签都可独立于其他书签来遍历集合。
 
 
01.class Program  
02.{  
03.    static void Main(string[] args)  
04.    {  
05.        CountingEnumerable counter = new CountingEnumerable();  
06.        foreach (int x in counter)  
07.        {  
08.            Console.WriteLine(x);  
09.        }  
10.  
11.        Console.ReadKey();  
12.    }  
13.}  
14.  
15.class CountingEnumerable : IEnumerable<int>  
16.{  
17.    public IEnumerator<int> GetEnumerator()  
18.    {  
19.        return new CountingEnumerator(); // 返回一个新的迭代器,是为了维护状态  
20.    }  
21.  
22.    // 由于IEnumerable<T>继承IEnumerable,两个接口的GetEnumerator方法同名  
23.    // 所以对于非泛型的IEnumerable的GetEnumerator方法使用显式接口实现。  
24.    // (如果IEnumerable<T>没有继承IEnumerable,那么一个只支持使用非泛型IEnumerable的  
25.    // 方法将无法使用IEnumerable<T>)  
26.    IEnumerator IEnumerable.GetEnumerator()  
27.    {  
28.        return GetEnumerator(); // IEnumerator是IEnumerator<T>的基类  
29.    }  
30.}  
31.  
32.class CountingEnumerator : IEnumerator<int>  
33.{  
34.    int current = -1;  
35.  
36.    public bool MoveNext()  
37.    {  
38.        current++;  
39.        return current < 10;  
40.    }  
41.  
42.    public int Current { get { return current; } }  
43.  
44.    object IEnumerator.Current { get { return Current; } }  
45.  
46.    public void Reset()  
47.    {  
48.        current = -1;  
49.    }  
50.  
51.    // IEnumerator<T>继承了IDisposable,为了遍历完后清理状态,所以需要实现该方法  
52.    // 该方法在foreach循环完毕后自动调用  
53.    public void Dispose() { }   
54.}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值