了解Linq操作需先了解IEnumerable可枚举类型–可迭代类型,因为Linq中的很多函数的返回值类型和传入的形参类型都是IEnumerable的。

IEnumerable可枚举类型–可迭代类型
只要一个类型实现了IEnumerable接口,就可以对这个类型进行遍历。

首选来看IEnumerable接口有一个需要实现的方法 GetEnumerator(),它的返回值类型是IEnumerator接口类型的,然后继续深入进去查看IEnumerator接口。
C#高级 09 IEnumerable可枚举类型--可迭代类型-LMLPHP

如图IEnumerator接口内部分为三部分:object类型的属性值和两个bool类型的方法
C#高级 09 IEnumerable可枚举类型--可迭代类型-LMLPHP

所以当我们使用IEnumerable时,将一个类继承它,然后需要实现一个返回值类型为IEnumerator类型的GetEnumerator()方法。给出示例代码如下所示:

class Student : IEnumerable
{
    public int Id { get; set; }
    public IEnumerator GetEnumerator()
    {
        // yield关键词他是一个迭代器,相当于实现了IEnumerator枚举器
        //yield return "Ant编程1";
        //yield return "Ant编程2";
        //yield return "Ant编程3";
        string[] student = { "Ant编程1", "Ant编程2", "Ant编程3" };
        return new StudentEnumerator(student);
    }    
}

 internal class StudentEnumerator : IEnumerator
 {
     string[] _student;
     int _position = -1;

     public StudentEnumerator(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;
     } 
 }

上述代码中,Student 类继承了IEnumerable接口,并实现了其中的GetEnumerator()。
GetEnumerator()返回为 new StudentEnumerator(student)是一个返回值为 IEnumerator的对象;
StudentEnumerator类集成了IEnumerator接口,实现了Current属性和MoveNext()和Reset()方法。

现在只需要在main函数中遍历Student对象,就可以看到IEnumerable枚举类型内部遍历的过程,示例代码如下:

internal class Program
{
    static void Main(string[] args)
    {
        int[] array = { 1, 2, 3, 4, 5 };
        int i = 1;
        string str = "Ant编程";
        Student student = new Student { Id = 1 };

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

这里在foreach遍历时,会先进入IEnumerable接口实现类的GetEnumerator()的返回值为IEnumerator接口类型的实现方法的MoveNext()内后,再继续下一步遍历。

01-09 19:33