6IEnumerable可枚举类型接口

IEnumerable:可枚举类型,可迭代类型
IEnumerator:枚举器

让类实现可以遍历

字符串和数组还有集合都可以直接进行foreach遍历,是因为他们都继承了IEnumerable接口并且实现了该接口。
我们自己定义的类不能遍历,如果我们要实现可以遍历的话,就要让自定义类也实现IEnumerable接口,etEnumerator方法就是用于遍历时访问的

流程:

1,创建一个类,继承IEnumerable接口并且实现里面的方法,我们在GetEnumerator方法里写一些循环遍历时要输出的数据用于演示:

public class Student : IEnumerable
    {
        public int ID { get; set; }
        public int ID2 { get; set; }

		//迭代输出时候用到的方法
        public IEnumerator GetEnumerator()
        {

            yield return "风华正茂1";
            yield return "风华正茂2";
            yield return "风华正茂3";
			//如果真的要遍历类的成员,就用yield return 类成员格式即可,如:yield returnID
        }

    }


2,接着我们就可实例化调用遍历这个类了

Student student = new Student();

            foreach (var item in student)
            {
                Console.WriteLine(item);
            }

输出结果:
image

GetEnumerator()方法里的yield关键字就是将要遍历的内容转为IEnumerator类型然后在输出的额时候就可以遍历这个枚举器了


GetEnumerator()方法里的yield关键字的具体实现

这里我们在GetEnumerator()方法中返回一个字符串数组来讲解yield关键字的实现

1,还是用上面那个类作为IEnumerable的实现,我们方法GetEnumerator()方法的返回值是IEnumerator枚举器类型,所以我们创建一个类,继承于IEnumerator接口,用来充当IEnumerator类,因为是要返回一个字符串数组枚举器,所以我们在类里定义一个字符串数组类型的字段,用来存在GetEnumerator()方法中需要返回的字符串数组,还需要定义一个下标,用来记录每次迭代时的位置。


//在循环时,每次循环都会用到该类里的方法,但是该类只会创建一次,就是开始循环的时候
    public class StudentIEnumerator : IEnumerator
    {


        string[] _student;


        int _position = -1;//用于记录位置,类似于数组中下标的作用,初始值为-1表示还没有指向数组里的元素

        //通过构造函数,实例化的时候将要遍历的字符串传进来
        public StudentIEnumerator(string[] student)
        {
            this._student = student;
        }


        //属性,表示当前从数组里取出的数据
        public object Current
        {
            get
            {
                if (_position == -1)//表示还没有开始遍历
                {
                    throw new InvalidOperationException();//抛一个异常
                }

                if (_position >= _student.Length)//表示超出了范围
                {
                    throw new InvalidOperationException();//抛一个异常
                }

                return _student[_position];//从数组里取出数据

            }
        }

        //移动到下一个,在外面没循环一次就会调用一次这个方法,让操作推进到下一个
        public bool MoveNext()
        {
            if (_position < _student.Length - 1)
            {
                _position++;
                return true;
            }
            else
            {
                return false;
            }
        }


        //重置下标
        public void Reset()
        {
            _position = -1;
        }

    }

2,在类的GetEnumerator方法里将要遍历的字符串数组用StudentIEnumerator类型返回即可

public class Student : IEnumerable
    {

        public int ID { get; set; }
        public int ID2 { get; set; }

        public IEnumerator GetEnumerator()
        {
            string[] students = { "张三", "李四" };//我们如果要循环类的成员时,可以将数组该为该类的类型,然后在里面放入成员即可
			
            return new StudentIEnumerator(students);
        }

    }

3,循环这个类即可

Student student = new Student();

            foreach (var item in student)
            {
                Console.WriteLine(item);
            }
posted @ 2021-11-02 11:55  青仙  阅读(94)  评论(0编辑  收藏  举报