11.C#迭代器(六章6.1)
今天我们说下C#中的迭代器,首先引出一些关于迭代的概念,后面举出代码供大家讨论。
迭代器模式是行为模式的一种范例,行为模式是一种简化对象之间通信的一种设计模式。在.NET中使用IEnumerator和IEnumerable接口及它们的泛型等价物来封装的,如果一个类型实现了IEnumerable接口,就说明它是可迭代的,调用GetEnumerator方法返回IEnumerator的实现,这是迭代器本身。
C#1使用foreach语句实现了访问迭代器的内置支持,foreach语句会被编译成使用GetEnumerator和MoveNext方法以及Current属性。C#中迭代器只能向后访问,而C++中迭代器可以支持前后访问。
背景,假设有一个关于学生的队列,每个学生依次报出自己的名字,Student类如下
1 class Student 2 { 3 public string Name { get; set; } 4 5 public Student(string name) 6 { 7 Name = name; 8 } 9 10 public void SayName() 11 { 12 Console.WriteLine(Name); 13 } 14 }
有一个实现IEnumerable的Queue的泛型类,如下
1 class Queue<T> : IEnumerable<T> where T : class 2 { 3 public List<T> objects = new List<T>(); 4 5 public Queue(List<T> list) 6 { 7 objects = list; 8 } 9 10 //实现从IEnumerable中的GetEnumerator方法 11 /* 12 个人觉得这个方法在迭代中只会调用一次,不然每次都返回一个新的QueueIterator<T>对象,位置记录都会重置为-1 13 */ 14 public IEnumerator<T> GetEnumerator() 15 { 16 return new QueueIterator<T>(this); 17 } 18 19 IEnumerator IEnumerable.GetEnumerator() 20 { 21 throw new NotImplementedException(); 22 } 23 }
使用GetEnumerator方法返回一个迭代器,而迭代器需要实现IEnumerator接口,如下
1 class QueueIterator<T> : IEnumerator<T> where T : class 2 { 3 private ConsoleDemo.Chapter6.Queue<T> q = null; 4 5 int startPoint = -1; //用于保存游标的位置 6 7 public QueueIterator(ConsoleDemo.Chapter6.Queue<T> q) 8 { 9 this.q = q; 10 } 11 12 //返回合适位置上的T类型实例,这个例子中调用提这个自动属性 13 public T Current 14 { 15 get 16 { 17 if (startPoint==-1 || startPoint==q.objects.Count) 18 { 19 throw new InvalidOperationException(); 20 } 21 int index = startPoint + q.objects.Count; 22 index = index % q.objects.Count; 23 return q.objects[index]; 24 } 25 } 26 27 object IEnumerator.Current 28 { 29 get 30 { 31 if (startPoint == -1 || startPoint == q.objects.Count) 32 { 33 throw new InvalidOperationException(); 34 } 35 int index = startPoint + q.objects.Count; 36 index = index % q.objects.Count; 37 return q.objects[index]; 38 } 39 } 40 41 public void Dispose() 42 { 43 44 } 45 46 public bool MoveNext() 47 { 48 if (startPoint != q.objects.Count) 49 { 50 startPoint++; 51 } 52 return startPoint < q.objects.Count; 53 } 54 //当迭代结束后,会调用这个方法,则下一次迭代后重新从第一个位置开始 55 public void Reset() 56 { 57 startPoint = -1; 58 } 59 }
分别要去实现从IEnumerator中的Current属性、Dispose方法(有必要的话)、MoveNext方法、Reset方法。使用C#2中的yield语句可以简化迭代器,再下一篇中再说。
请斧正。
分类:
深入理解C#
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?