zoukankan      html  css  js  c++  java
  • 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语句可以简化迭代器,再下一篇中再说。

      请斧正。

      

  • 相关阅读:
    云计算OpenStack核心组件---keystone身份认证服务(5)
    云计算OpenStack环境搭建(4)
    云计算OpenStack共享组件---Memcache缓存系统(3)
    云计算OpenStack共享组件---信息队列rabbitmq(2)
    【面试题41】和为s的两个数字VS和为s的连续整数序列
    反转单链表
    【面试题40】数组中只出现一次的数字
    【面试题39】二叉树的深度
    【面试题38】数字在排序数组中出现的次数
    最少钱币问题
  • 原文地址:https://www.cnblogs.com/a2htray/p/4197843.html
Copyright © 2011-2022 走看看