文章目录
- 1. 枚举
- 1.1 枚举结构梳理
- 1.2 枚举完整代码
- 1.3 枚举知识点补充
- 2. 迭代两种命名空间接口
- 3. yield语句
1. 枚举
1.1 枚举结构梳理
结构图
上图内容可能依旧不通俗易懂,这里使用最简明的话语告诉大家实现方式.
- foreach语句就是集合的遍历操作,我们如果想要完成一个集合的遍历操作我们需要做哪些操作呢?毫无疑问的,我们首先需要拥有元素的读取操作,还需要一个数据的滚动操作(读取下一个元素)。这两个通用的方法读取操作我们设置为Current属性,滚动操作设置为MoveNext方法,这些东西全部都被我们封装到IEnumerator接口当中,我们通过实现这个接口完成相应的操作
public class Data : IEnumerator{
public int[] data = {1, 2, 3, 4, 5};
int position = -1;
object IEnumerator.Current{
get{
return data[position];
}
}
public bool MoveNext(){
position++;
return (position < 5);
}
public void Reset(){
position = -1;
}
}
- 最核心的步骤IEnumerator接口完成了,现在我们需要关心的就是如何在类当中让我们可以找到这个接口,这个时候我们其实只需要实现一个名为GetEnumerator()的方法即可,这个方法需要返回实现IEnumerator接口的实现类即可
public class GetDate{
public IEnumerator GetEnumerator(){
return new Data();
}
}
- 最后就可以使用了,foreach先去类里面找GetEnumerator()方法,通过这个方法拿到IEnumerator接口的实现类,再通过这个实现类内部定义的操作对数据进行遍历,这个就是foreach关键字的调用原理
static void Main(){
GetDate getDate = new GetDate();
foreach(int x in getDate){
Console.WriteLine(x);
}
}
1.2 枚举完整代码
using System;
using System.Collections;
public class Data : IEnumerator
{
public int[] data = {1, 2, 3, 4, 5};
int position = -1;
object IEnumerator.Current{
get{
return data[position];
}
}
public bool MoveNext(){
position++;
return (position < 5);
}
public void Reset(){
position = -1;
}
}
public class GetDate{
public IEnumerator GetEnumerator(){
return new Data();
}
}
class App{
static void Main(){
GetDate getDate = new GetDate();
foreach(int x in getDate){
Console.WriteLine(x); // 输出: 1 2 3 4 5
}
}
}
1.3 枚举知识点补充
- 通过上述步骤我们其实已经大概了解了foreach的内部调用原理了,但是对于手写的GetEnumerator方法我们推出了一个新的接口IEnumerable去包装它,其实它的本质也就是代替了我们在方法当中手写GetEnumerator,也是一个很好的纠错提示,这样子可以更好的防止我们自己手写方法名字错误
public class GetDate : IEnumerable{ // 和我们上述步骤的方法没有太大区别,也就是加入一个接口的实现
public IEnumerator GetEnumerator(){
return new Data();
}
}
2. 迭代两种命名空间接口
- 非泛型命名空间:System.Collection
- 泛型命名空间:System.Collection.Generic.IEnumerator