美文网首页
协程(三)IEnumerable、IEnumerator、for

协程(三)IEnumerable、IEnumerator、for

作者: 86a262e62b0b | 来源:发表于2019-07-29 13:30 被阅读0次

协程(一)基本使用
协程(二)协程什么时候调用
协程(三)IEnumerable、IEnumerator、foreach、迭代
协程(四)yield与迭代器
协程(五)简单模拟协程
协程(六)有关优化

一.文档

二. IEnumerable和IEnumerator

简单看下两个接口的实现


IEnumerable IEnumerator IEnumerator

五.实现自己的集合类、迭代器

常用集合有list、String等能使用foreach遍历。那我们如何让自己的类也能使用foreach遍历?

  • 你会发现List、String等集合,里面已经实现了IEnumerable接口

    和这个: image.png
  • 所以,我们也可以实现IEnumerator接口,比如文档里面的代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Project2
{
    class Test
    {
        static void Main()
        {
            Person[] peopleArray = new Person[3]
            {
                new Person("John", "Smith"),
                new Person("Jim", "Johnson"),
                new Person("Sue", "Rabon"),
            };

            People peopleList = new People(peopleArray);

            //(peopleList as IEnumerable).GetEnumerator();//显示调用接口 这个知识点属于接口,跳过

            Console.WriteLine("Before foreach");
            foreach (Person p in peopleList)
            { 
                Console.WriteLine(p.firstName + " " + p.lastName);
            }

            Console.ReadLine();
        }
    }
    public class Person
    {
        public Person(string fName, string lName)
        {
            this.firstName = fName;
            this.lastName = lName;
        }

        public string firstName;
        public string lastName;
    }

    //集合类 元素为Person, 就像List<int>集合,元素为int
    public class People : IEnumerable
    {
        private Person[] _people;

        //构造函数,初始化数组
        public People(Person[] pArray)
        {
            _people = new Person[pArray.Length];

            for (int i = 0; i < pArray.Length; i++)
            {
                _people[i] = pArray[i];
            }
        }

        /*
          foreach会调用“GetEnumerator”方法来获取迭代器类
          即使你没有实现IEnumerable接口,但有GetEnumerator方法,也能使用foreach
          接口所定义的方法,仅仅起到规范作用。
             */
        IEnumerator IEnumerable.GetEnumerator() //此处为显示接口方法
        {
            Console.WriteLine("IEnumerable.GetEnumerator");
            return (IEnumerator)GetEnumerator();
        }

        //foreach,会先找GetEnumerator方法,在找接口的GetEnumerator方法,所以下面的方法覆盖了上面接口的方法,可以修改方法名来避免
        public PeopleEnum GetEnumerator()
        {
            Console.WriteLine("GetEnumerator");
            return new PeopleEnum(_people);//返回枚举器实例
        }
    }

    //枚举器类
    public class PeopleEnum : IEnumerator
    {
        public Person[] _people;

        // Enumerators are positioned before the first element
        // until the first MoveNext() call.
        int position = -1;

        public PeopleEnum(Person[] list)
        {
            _people = list;
        }

        public bool MoveNext()
        {
            position++;
            return (position < _people.Length);
        }

        public void Reset()
        {
            position = -1;
        }

        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }

        public Person Current
        {
            get
            {
                try
                {
                    return _people[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
    }
}
  • 幸运地是,无需记住所有这些细节。 foreach 语句会为你处理所有这些细微差别。 编译器会为所有这些构造生成正确的代码。
  • foreach 语句可扩展为使用 IEnumerable<T> 和 IEnumerator<T> 接口的标准用语,以便循环访问集合中的所有元素。 还可最大限度减少开发人员因未正确管理资源所造成的错误。

相关文章

网友评论

      本文标题:协程(三)IEnumerable、IEnumerator、for

      本文链接:https://www.haomeiwen.com/subject/tobmrctx.html