概述
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方法(将数据元素添加到私有数组字段中),而调用类的其他方法时,其实就是对私有数组类型字段的操作。
所以对于这些集合来说,本质上集合中的所有元素都是保存在一个私有数组类型的字段中,众所周知,对于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>中是如何定义的。
哇哦,原来迭代器是这样的呀!!!!
自定义一个简单的支持迭代的集合
下面我们就来自定义一个支持迭代器的集合
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() { } } }
测试自定义集合的迭代功能:
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,如需转载请自行联系原作者