本文共 4176 字,大约阅读时间需要 13 分钟。
从这两个接口的用词选择上,也可以看出其不同:
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()方法 可以获得一个可用于循环访问集合的 对象 Listlist = new List () { "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(); }}
03:自定义自己可以遍历的类
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
04: yield return 自动生成枚举器
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]; } } }}
转载地址:http://hcrxo.baihongyu.com/