且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

IEnumerable和IEnumerator

更新时间:2022-09-19 23:40:08

概述

IEnumerable和IEnumerator接口存在的意义:用来实现迭代的功能!

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface IEnumerable
{
    IEnumerator GetEnumerator();
}
 
public interface IEnumerator
{
    object Current { get; }
 
    bool MoveNext();
 
    void Reset();
}

迭代的原理

首先来说一下集合实现的原理:对于ArrayList、List<T>等集合,类中有一个私有的数组类型字段,向集合中添加数据时调用Add方法(将数据元素添加到私有数组字段中),而调用类的其他方法时,其实就是对私有数组类型字段的操作。

IEnumerable和IEnumerator ArrayList
IEnumerable和IEnumerator List

所以对于这些集合来说,本质上集合中的所有元素都是保存在一个私有数组类型的字段中,众所周知,对于ArrayList或者List<T>都可以使用foreach进行迭代,查看集合中的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
static void Main(string[] args)
{
    List<string> strs=new List<string>();
    strs.Add("DD");
    strs.Add("FF");
    strs.Add("VV");
    strs.Add("WW");
    foreach (String str in strs)
    {
        Console.WriteLine(str);
    }
    Console.ReadKey();
}

上述这个foreach的迭代的过程是如何实现的呢?foreach为什么可以逐个遍历所以集合中的元素呢?下面我们就用IL反汇编程序来查看上述代码的foreach部分的IL!

看不懂?没关系啦,那么我们就来大致的猜想一下,我们的foreach生成了这么一大坨的IL中居然有Enumerator什么的,难道跟这个有关系吗?恰巧听说IEnumerable和IEnumrator用来实现迭代,恰恰巧我们的ArrayList、List<T>集合都是实现了IEnumerable接口。那么我们就来做的大胆的假设,foreach其实就是执行跟IEnumerable和IEnumrator接口相关的代码,并对保存集合的私有数组字段的索引进行操作,从而来实现迭代的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void Main(string[] args)
{
    List<string> strs=new List<string>();
    strs.Add("DD");
    strs.Add("FF");
    strs.Add("VV");
    strs.Add("WW");
    IEnumerator<string> items = strs.GetEnumerator();
    while (items.MoveNext())
    {
        Console.WriteLine(items.Current);
    }
    Console.ReadKey();
}

这段代码也同样实现了对集合元素迭代的功能!在来看一下这个迭代生成的相关IL。

嘿嘿,对比两者生成的IL,目测他们的执行过程中调用的IL指令大体上是一致的(IL指令啥的暂时我也不是很了解),所以我们的猜想应该是正确的,foreach在本质上其实就是通过ArrayList、List<T>中定义的GetEnumerator方法,以及后续的代码实现的!下面就来看看List<T>中是如何定义的。

IEnumerable和IEnumerator List<T>

哇哦,原来迭代器是这样的呀!!!!

自定义一个简单的支持迭代的集合

下面我们就来自定义一个支持迭代器的集合

IEnumerable和IEnumerator
public class UserDefinedCollection<T>:IEnumerable<T>
    {
        private List<T> list = new List<T>();

        public UserDefinedCollection(List<T> param)
        {
            list = param;
        }
        public IEnumerator<T> GetEnumerator()
        {
            return new UserDefinedEnum<T>(list);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        private sealed class UserDefinedEnum<T>:IEnumerator<T>
        {
            private List<T> list = null;
            private int _CurrentIndex;
            private T _CurrentElement;

            public UserDefinedEnum(List<T> param)
            {
                this.list = param;
                this._CurrentIndex = 0;
                _CurrentElement = default(T);
                
            }

            public T Current
            {
                get 
                {
                    return _CurrentElement;
                }
            }

            object IEnumerator.Current
            {
                get { return Current; }
            }

            public bool MoveNext()
            {
                if (this._CurrentIndex < this.list.Count)
                {
                    this._CurrentElement = this.list[this._CurrentIndex++];
                    return true;
                }
                return false;
            }

            public void Reset()
            {
                this._CurrentElement = default(T);
                this._CurrentIndex = 0;
            }
            public void Dispose()
            {
                
            }
        }

    }
IEnumerable和IEnumerator

 测试自定义集合的迭代功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List<string> strs=new List<string>();
strs.Add("DD");
strs.Add("FF");
strs.Add("VV");
strs.Add("WW");
UserDefinedCollection<String> user = new UserDefinedCollection<string>(strs);
IEnumerator<string> iEnumerator = user.GetEnumerator();
 
while (iEnumerator.MoveNext())
{
    Console.WriteLine(iEnumerator.Current);
}
 
foreach (String str in user)
{
    Console.WriteLine(str);
}

 

扩展:由模型绑定中,绑定泛型类型时学习到泛型相关的知识!

  


本文转自武沛齐博客园博客,原文链接:http://www.cnblogs.com/wupeiqi/p/3472980.html,如需转载请自行联系原作者