从这两个接口的用词选择上,也可以看出其不同:
a) IEnumerable是一个声明式的接口,声明实现该接口的类是可枚举。
b) IEnumerator是一个实现式的接口,IEnumerator对象说明如何实现枚举器。
Foreach语句隐式调用集合的无参GetEnumerator方法(不论集合是否有实现IEnumerable接口,但只要有无参GetEnumerator方法并返回IEnumerator就可遍历)。
集合类为什么不直接实现IEnumerable和IEnumerator接口?
这样是为了提高并发性。Eg:一个遍历机制只有一个Current,一旦并发就会出错。然而“将遍历机制与集合分离开来”如果要实现同时遍历同一个集合,只需由集合IEnumerable.GetEnumerator() 返回一个新的包含遍历机制(IEnumerator)的类实例即可。
01:foreach在数组集合的遍历时会被经常用到,例如
使用foreach做遍历确实很方便,然而并不是每一种类型都能使用foreach进行遍历操作,只有实现了IEnumerable接口的类(也叫做可枚举类型)才能进行foreach的遍历操作,集合和数组已经实现了这个接口,所以能进行foreach的遍历操作
02:
foreach是对集合进行遍历,而集合都继承Array类
foreach结构设计用来和可枚举类型一起使用,只要给它的遍历对象是可枚举类型
只有实现了IEnumerable接口的类(也叫做可枚举类型)才能进行foreach的遍历操作,集合和数组已经实现了这个接口,所以能进行foreach的遍历操作
集合继承IEnumerable这个接口,而IEnumerable的 IEnumerator GetEnumerator()方法 可以获得一个可用于循环访问集合的 对象
List<string> list = new List<string>() { "252", "哈哈哈", "25256", "春天里的花朵" };
Console.WriteLine(list.GetType().Name);
IEnumerator listEnumerator = list.GetEnumerator();
while (listEnumerator.MoveNext())
{
Console.WriteLine(listEnumerator.Current);
}
listEnumerator.Reset();
namespace System.Collections
{
//
// 摘要:
// 公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。 若要浏览此类型的.NET Framework 源代码,请参阅Reference Source。
[ComVisible(true)]
[Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
public interface IEnumerable
{
//
// 摘要:
// 返回循环访问集合的枚举数。
//
// 返回结果:
// 一个可用于循环访问集合的 System.Collections.IEnumerator 对象。
[DispId(-4)]
IEnumerator GetEnumerator();
}
}
//枚举器内部的方法
namespace System.Collections
{
//
// 摘要:
// 支持对非泛型集合的简单迭代。
[ComVisible(true)]
[Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
public interface IEnumerator
{
//
// 摘要:
// 获取集合中位于枚举数当前位置的元素。
//
// 返回结果:
// 集合中位于枚举数当前位置的元素。
object Current { get; }
//
// 摘要:
// 将枚举数推进到集合的下一个元素。
//
// 返回结果:
// 如果枚举数已成功地推进到下一个元素,则为 true;如果枚举数传递到集合的末尾,则为 false。
//
// 异常:
// T:System.InvalidOperationException:
// 创建枚举器后,已修改该集合。
bool MoveNext();
//
// 摘要:
// 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
//
// 异常:
// T:System.InvalidOperationException:
// 创建枚举器后,已修改该集合。
void Reset();
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 枚举器和迭代器
{
class Program
{
static void Main(string[] args)
{
MyClass myClass=new MyClass();
while (myClass.MoveNext())
{
Console.WriteLine(myClass.Current);
}
myClass.Reset();
IEnumerator iEnumerator=myClass.GetEnumerator();
while (iEnumerator.MoveNext())
{
Console.WriteLine(iEnumerator.Current);
}
myClass.Reset();
foreach (string item in myClass.Names)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
//可枚举的类型可以被枚举遍历
class MyClass: IEnumerator,IEnumerable
{
public string[] Names { get; set;}
public MyClass()
{
Names = new string[] {"22", "就", "333"};
}
private int postion = -1;
//枚举器的方法
public object Current
{
get
{
if (postion>=0&&postion<Names.Length)
{
return Names[postion];
}
return null;
}
}
public bool MoveNext()
{
if (postion<Names.Length)
{
postion++;
return true;
}
else
{
return false;
}
}
public void Reset()
{
postion = -1;
}
//获取枚举器
public IEnumerator GetEnumerator()
{
return new MyClass();
}
}
}
namespace 迭代器
{
class Program
{
static void Main(string[] args)
{
MyClass myClass=new MyClass();
foreach (var item in myClass)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
public class MyClass : IEnumerable
{
public string[] Names { get; set; }
public MyClass()
{
Names = new string[] { "22", "就", "333" };
}
public IEnumerator GetEnumerator()
{
for (int i = 0; i < Names.Length; i++)
{
yield return Names[i];
}
}
}
}