foreach 迭代器的实现
foreach 迭代器可以遍历所有实现了IEnumerable接口或者提供了 IEnumerable实现的类。
MSDN解释:
在 C# 中,集合类并非必须严格从 IEnumerable 和 IEnumerator 继承才能与 foreach 兼容;只要类有所需的 GetEnumerator、MoveNext、Reset 和 Current 成员,便可以与 foreach 一起使用。省略接口的好处为,使您可以将 Current 的返回类型定义得比 object 更明确,从而提供了类型安全。
查看IEnumerable的实现,只是简单的返回了一个IEnumerator 对象,所有的处理都被委托到了IEnumerator。
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
public interface IEnumerator
{
object Current { get; }//获取集合中的当前元素
bool MoveNext();//将枚举数推进到集合的下一个元素
void Reset();//将枚举数设置为其初始位置,该位置位于集合中第一个元素之前
}
简单示例
class MyEnumerable:IEnumerable
{
int[] values;
public MyEnumerable(int[] values)
{
this.values = values;
}
#region IEnumerable 成员
public IEnumerator GetEnumerator()
{
return new MyEnumerator(this);
}
#endregion
class MyEnumerator : IEnumerator
{
MyEnumerable parent;
int position = -1;
public MyEnumerator(MyEnumerable parent)
{
this.parent = parent;
}
#region IEnumerator 成员
public object Current
{
get
{
return parent.values[position];
}
}
public bool MoveNext()
{
return ++position < parent.values.Length;
}
public void Reset()
{
position = -1;
}
#endregion
}
}
由于 IEnumerator接口定义的 Current类型为 Object,所以在使用foreach循环中,获取到的元素类型也是objec。
static void Main(string[] args)
{
int[] values = { 1, 2, 3 };
MyEnumerable collection = new MyEnumerable(values);
foreach (var value in collection)
{
int temp = value + 1;//编译出错,无法将objec和int类型相加
Console.WriteLine(temp);
}
Console.Read();
}
可以显示指定foreach中的元素类型 比如 foreach (int value in collection) ,在每次遍历的时候 执行一次强制转换,如果是值类型,还会涉及到装箱和拆箱。
所以我们使用IEnumerable<T>替代IEnumerable
class MyEnumerable : IEnumerable<int> { int[] values; public MyEnumerable(int[] values) { this.values = values; } public IEnumerator<int> GetEnumerator() { return new MyEnumerator(this); } class MyEnumerator : IEnumerator<int> { public int Current { get { return parent.values[position]; } }
……………… } }
最主要的区别就是 Current 的类型为定义的泛型类型,此处为int。
迭代器的实现过于繁琐, 可以使用 yield return 替代繁琐的IEnumerator内嵌类
public IEnumerator<int> GetEnumerator()
{
for (int i = 0; i < values.Length; i++)
yield return values[i];
}
yield return 内部实现了一个状态机,具体就不展开了~~

浙公网安备 33010602011771号