IEnumerable、IEnumerator接口(迭代器)

介绍

IEnumerable 提供了可以迭代的能力,而这种能力是通过内部的可迭代对象来实现了,这个对象就是IEnumerator
有了它们,我们不需要将内部集合暴露出去,外界只需要访问我的迭代器接口方法即可遍历数据。

foreach

在C#中,使用foreach语句来遍历集合。foreach语句是微软提供的语法糖,使用它可以简化C#内置迭代器的使用复杂性。编译foreach语句,会生成调用GetEnumerator和MoveNext方法以及Current属性的代码。
反编译foreach,生成类似下面这段代码:

IEnumerator<Student> studentEnumerator = studentList.GetEnumerator();
while (studentEnumerator.MoveNext())
{
     var currentStudent = studentEnumerator.Current as Student;
     Console.WriteLine("Id = {0}, Name = {1}, Age = {2}", currentStudent.Id, currentStudent.Name, currentStudent.Age);
}

案例

案例1:给类增加迭代器功能

public class StudentSet : IEnumerable
 {
     private Student[] students;
     public StudentSet(Student[] inputStudents)
     {
         students = new Student[inputStudents.Length];
         for (int i = 0; i < inputStudents.Length; i++)
         {
             students[i] = inputStudents[i];
         }
     }
     IEnumerator IEnumerable.GetEnumerator()
     {
         return (IEnumerator)GetEnumerator();
     }
     public StudentEnumerator GetEnumerator()
     {
         return new StudentEnumerator(students);
     }
 }
 public class StudentEnumerator : IEnumerator
 {
     public Student[] students;
     int position = -1;
     public StudentEnumerator(Student[] students)
     {
         this.students = students;
     }
     public bool MoveNext()
     {
         position++;
         return (position < students.Length);
     }
     public void Reset()
     {
         position = -1;
     }
     object IEnumerator.Current
     {
         get
         {
             return Current;
         }
     }
     public Student Current
     {
         get
         {
             try
             {
                 return students[position];
             }
             catch (IndexOutOfRangeException)
             {
                 throw new InvalidOperationException();
             }
         }
     }
 }

案例2:使用yield实现迭代器功能
有两种实现迭代器的方式,一是自己继承IEnumerable接口,比较复杂;二是使用yield,简化操作。

    public class MyCollection
    {
        private int[] list = new int[] { 1, 2, 3, 4 };

        public IEnumerator<int> GetEnumerator()
        {
            for (int i = 0; i < list.Length; i++)
            {
                yield return list[i];
            }
        }
    }
 MyCollection col = new MyCollection();
            foreach (var item in col)
            {
                Console.WriteLine(item);
            }
posted @ 2019-12-01 21:18  .Neterr  阅读(190)  评论(0编辑  收藏  举报