一、前言
假设存在一个数组,其遍历模式是根据索引进行遍历的;又假设存在一个HashTable,其遍历模式是根据键值进行遍历的;无论哪种集合,如果它们的遍历没有一个共同的接口,那么在客户端进行调用的时候,就需要对每种集合的具体类型进行它们各自的具体代码编写,当需求发生变化时,就必须修改我们的代码。并且客户端过多的关注集合内部的实现,代码的移植性就会变差,违反了开闭原则,这个时候迭代器就诞生了,现在我们来根据上一章 foreach遍历原理(一)实现我们自己的迭代器。
二、代码示例
class Program { static void Main(string[] args) { //使用接口IMyEnumerable代替MyList IMyEnumerable list = new MyList(); //得到迭代器,在循环中针对迭代器编码,而不是集合MyList IMyEnumerator enumerator = list.GetEnumerator(); while (enumerator.MoveNext()) { object current = enumerator.Current; Console.WriteLine(current); } Console.ReadKey(); } /// <summary> /// 要求所有的迭代器全部实现该接口 /// </summary> interface IMyEnumerator { bool MoveNext(); object Current { get; } } /// <summary> /// 要求所有的集合实现该接口 /// 这样一来,客户端就可以针对该接口编码, /// 而无须关注具体的实现 /// </summary> interface IMyEnumerable { IMyEnumerator GetEnumerator(); int Count { get; } } class MyList : IMyEnumerable { object[] items = new object[10]{0,1,2,3,4,5,6,7,8,9}; IMyEnumerator myEnumerator; public object this[int i] { get { return items[i]; } set { this.items[i] = value; } } public int Count { get { return items.Length; } } public IMyEnumerator GetEnumerator() { if (myEnumerator == null) { myEnumerator = new MyEnumerator(this); } return myEnumerator; } } class MyEnumerator : IMyEnumerator { int index = 0; MyList myList; public MyEnumerator(MyList myList) { this.myList = myList; } public bool MoveNext() { if (index + 1 > myList.Count) { index = 1; return false; } else { index++; return true; } } public object Current { get { return myList[index - 1]; } } } }
运行结果:
三、疑问——为什么不把 IMyEnumerable 和 IMyEnumerator 接口写在同一个接口里面,例如新建一个接口名字为 IForeach,不使用迭代器,也能输出上面的结果
class Program { static void Main(string[] args) { IForeach iForeach = new MyList(); while (iForeach.MoveNext()) { object current = iForeach.Current; Console.WriteLine(current); } Console.ReadKey(); } interface IForeach { bool MoveNext(); object Current { get; } int Count { get; } } class MyList : IForeach { object[] items = new object[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int index = 0; public object this[int i] { get { return items[i]; } set { this.items[i] = value; } } public int Count { get { return items.Length; } } public bool MoveNext() { if (index + 1 > Count) { index = 1; return false; } else { index++; return true; } } public object Current { get { return this[index - 1]; } } } }
四、如果我现在有新需求要倒序输出,那么按照上面“三”的做法,就必须修改 MyList 类里面的代码,而且是大改。如果使用迭代器 ,我们只需要重新写类继承迭代器IMyEnumerator,替换一下迭代器,就能够实现MyList 的倒序输出。
新增一个倒序迭代器
class MyInvertEnumerator : IMyEnumerator { int index = 0; MyList myList; public MyInvertEnumerator(MyList myList) { this.myList = myList; index = myList.Count; } public bool MoveNext() { if (index - 1 <0) { index = myList.Count; return false; } else { index--; return true; } } public object Current { get { return myList[index]; } } }
修改MyList集合里面获取迭代器的方法,然后运行就能够
class MyList : IMyEnumerable { object[] items = new object[10]{0,1,2,3,4,5,6,7,8,9}; IMyEnumerator myEnumerator; public object this[int i] { get { return items[i]; } set { this.items[i] = value; } } public int Count { get { return items.Length; } } public IMyEnumerator GetEnumerator() { if (myEnumerator == null) { // myEnumerator = new MyEnumerator(this);//正序输出 myEnumerator = new MyInvertEnumerator(this);//倒序输出 } return myEnumerator; } }
倒序输出完整代码:
class Program { static void Main(string[] args) { //使用接口IMyEnumerable代替MyList IMyEnumerable list = new MyList(); //得到迭代器,在循环中针对迭代器编码,而不是集合MyList IMyEnumerator enumerator = list.GetEnumerator(); while (enumerator.MoveNext()) { object current = enumerator.Current; Console.WriteLine(current); } Console.ReadKey(); } /// <summary> /// 要求所有的迭代器全部实现该接口 /// </summary> interface IMyEnumerator { bool MoveNext(); object Current { get; } } /// <summary> /// 要求所有的集合实现该接口 /// 这样一来,客户端就可以针对该接口编码, /// 而无须关注具体的实现 /// </summary> interface IMyEnumerable { IMyEnumerator GetEnumerator(); int Count { get; } } class MyList : IMyEnumerable { object[] items = new object[10]{0,1,2,3,4,5,6,7,8,9}; IMyEnumerator myEnumerator; public object this[int i] { get { return items[i]; } set { this.items[i] = value; } } public int Count { get { return items.Length; } } public IMyEnumerator GetEnumerator() { if (myEnumerator == null) { // myEnumerator = new MyEnumerator(this);//正序输出 myEnumerator = new MyInvertEnumerator(this);//倒序输出 } return myEnumerator; } } class MyEnumerator : IMyEnumerator { int index = 0; MyList myList; public MyEnumerator(MyList myList) { this.myList = myList; } public bool MoveNext() { if (index + 1 > myList.Count) { index = 1; return false; } else { index++; return true; } } public object Current { get { return myList[index - 1]; } } } class MyInvertEnumerator : IMyEnumerator { int index = 0; MyList myList; public MyInvertEnumerator(MyList myList) { this.myList = myList; index = myList.Count; } public bool MoveNext() { if (index - 1 <0) { index = myList.Count; return false; } else { index--; return true; } } public object Current { get { return myList[index]; } } } }
迭代器就讲到这里了,谢谢大家。
时间: 2024-10-26 13:03:45