了解Linq操作需先了解IEnumerable可枚举类型–可迭代类型,因为Linq中的很多函数的返回值类型和传入的形参类型都是IEnumerable的。
IEnumerable可枚举类型–可迭代类型
只要一个类型实现了IEnumerable接口,就可以对这个类型进行遍历。
首选来看IEnumerable接口有一个需要实现的方法 GetEnumerator(),它的返回值类型是IEnumerator接口类型的,然后继续深入进去查看IEnumerator接口。
如图IEnumerator接口内部分为三部分:object类型的属性值和两个bool类型的方法
所以当我们使用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()内后,再继续下一步遍历。