飞道的博客

C#编程篇 第09部分 迭代器

236人阅读  评论(0)

第09部分 迭代器


1> 迭代器(iterator)

  • 迭代器有时又称光标(cursor)是程序的软件设计模式。迭代器模式提供了一个方法顺序访问一个聚合对象中的各个元素,而不是暴露其内部的标识。

  • 在表面效果上来看,是可以在容器对象(例如链表或数组)上遍历访问的接口,设计人员无需关心容器对象的内存分配的实现细节。

  • 可以使用foreach遍历的类,都是实现了迭代器的。


2> 标准迭代器的实现方法

  • 关键接口:IEnumerator,IEnumerable:using System.Collections;

  • 可以同时继承这两个接口实现其中的方法。

  • 自定义一个类型,用标准迭代器实现对该类对象的内部聚合对象的遍历,且不暴露其标识。

 class CustomList : IEnumerable, IEnumerator
    {
   
        private int[] List;
        public CustomList(int[] arr)
        {
   
            if (arr != null)
            {
   
                List = arr;
            }
        }
        private int position = -1;//设置任务
        public IEnumerator GetEnumerator()//实现IEnumerable
        {
   
            Reset();//复原光标
            return this;//继承了IEnumerator,返回自己//返回IEnumerator
        }
        public bool MoveNext()
    //方法表示光标移动到下一个元素,并判断光标是否溢出
        {
   
            ++position;//表示光标
            return position < List.Length;
    //当溢出时,表示当前遍历对象以达到最大光标位置。
        }
        public object Current => List[position];
    //当MoveNext返回true时,返回当前光标所在元素的值。
        public void Reset()
    //重新调用遍历时将光标复原,在GetEnumerator方法中调用。
        {
   
            position = -1;
        }
     }
  • GetEnumerator方法实现了IEnumerable接口,返回IEnumerator去进行它的方法,首先会调用Reset()方法将光标复原为-1;
  • 其它三个成员实现了IEnumerator的两个方法和一个成员。在foreach遍历时会调用其方法。
   class Program
    {
   
        static void Main(string[] args)
        {
   
            CustomList list = new CustomList(
                  new int[] {
    1, 5, 9, 6, 4, 7, 85, 5, 5 });
            foreach (var item in list)//
            {
   
                Console.WriteLine(item); 
            }
        }
    }

3> 标准实现自定义迭代器附件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace ConsoleApp7
{
   
    class CustomList : IEnumerable, IEnumerator
    {
   
        private int[] List;
        public CustomList(int[] arr)
        {
   
            if (arr != null)
            {
   
                List = arr;
            }
           
        }

        private int position = -1;
        public IEnumerator GetEnumerator()//实现IEnumerable
        {
   
            Reset();//复原光标
            return this;//继承了IEnumerator,返回自己//返回IEnumerator

        }
        public bool MoveNext()//方法表示光标移动到下一个元素,并判断光标是否溢出
        {
   
            ++position;//表示光标
            return position < List.Length;//当溢出时,表示当前遍历对象以达到最大光标位置。
        }
        public object Current => List[position];//当MoveNext返回true时,返回当前光标所在元素的值。

        public void Reset()//重新调用遍历时将光标复原,在GetEnumerator方法中调用。
        {
   
            position = -1;
        }
    }

    class Program
    {
   
        static void Main(string[] args)
        {
   
            CustomList list = new CustomList(new int[] {
    1, 5, 9, 6, 4, 7, 85, 5, 5 });
            foreach (var item in list)
            {
   
                Console.WriteLine(item); 
            }
        }
    }
}


4> foreach遍历的本质

  • 先获取in后面这个对象的IEnumerator:会调用对象其中的GetEnumerator方法来获取。

  • 执行得到这个IEnumerator对象中的MoveNext(),判定光标的位置并移动。

  • 当返回true时,会得到Current的值,并把其赋值给item


5> 用yield return语法糖实现迭代器

  • 所谓语法糖(糖衣语法)主要作用时将都咋逻辑简单化,可以增加程序的可读性,从而减少程序的可读性,从而减少程序代码出错的机会。

  • 关键接口 IEnumerable

命名空间 using System.Collections;

  • 让想要通过foreach遍历的自定义类型实现接口中的方法GetEnumerator即可,

使用yield return系统自动实现标准迭代器的方法逻辑。

  • 语法规则: yield 配合 IEnumerable使用,理解为暂时返回并保留当前状态,再次返回时,继续当前状态,直至遍历结束。
 class test : IEnumerable
    {
   
        private int[] List;
        public test(int[] arr)
        {
   
            if (arr!=null)
            {
   
                List = arr;
            }
        }
        public IEnumerator GetEnumerator()
        {
   
            for (int i = 0; i < List.Length; i++)
            {
   
                yield return List[i];
            }
        }
    }

5.1 yield语法糖为泛型实现迭代器

  • 使用同样的方法foreach迭代,用yield return 控制实现IEnumerable方法GetEnumerator。


转载:https://blog.csdn.net/weixin_52566131/article/details/116427867
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场