IEnumerator
实现 IEnumerator 接口的类才是真正的迭代器,它定义了各项元素被循环访问的逻辑。
// 实现 IEnumerator
public class WeekEnumerator : IEnumerator
{
string[] week = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
int position = -1;
public object Current => week[position];
public bool MoveNext()
{
position++;
return position < week.Length;
}
public void Reset()
{
position = -1;
}
}
// 循环迭代器
var week = new WeekEnumerator ();
while (week .MoveNext())
{
Debug.Log(week.Current);
}
yield return
yield 是一种语法糖,会自动实现 IEnumerator 接口的 Current、MoveNext 等方法。即完成 MonthEnumerator 所做的事。所以,语句中使用了 yield 关键字的方法、运算符或 get 访问器也是迭代器。
使用多个 yield 语句,可以代替手动实现 IEnumerator 的繁琐操作。
// 定义迭代器方法
IEnumerator GetWeek()
{
// 多个 yield 语句合起来生成了一个实现 IEnumerator 接口的类(相当于 WeekEnumerator )
// yield return 的返回类型是 IEnumerator
yield return "Mon";
yield return "Tue";
yield return "Wed";
yield return "Thu";
yield return "Fri";
yield return "Sat";
yield return "Sun";
}
// 循环这个迭代器方法
var week = GetWeek();
while (week.MoveNext())
{
Debug.Log(week.Current);
}
IEnumerable
IEnumerable 接口实际上就是简化了循环访问,包装了 IEnumerator 以便通过 foreach 进行循环
// IEnumerable 接口只有一个获取 IEnumerator 的方法
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
// 使用 foreach 循环 List,它是实现了 IEnumerable 接口的类型
var array = new List<int> { 100, 101, 102 };
foreach (var item in array)
{
Debug.Log(item);
}
// 这是编译器内部转换的 foreach 代码
var enumerator = array.GetEnumerator();
while (enumerator.MoveNext())
{
Debug.Log(enumerator.Current);
}
即,IEnumerator 类在使用 IEnumerable 接口包装后,可使用 foreach 循环,否则需使用 MoveNext 手动完成。C# 中自带集合,一般都实现自 IEnumerable 接口,方便可用 foreach 进行迭代。
使用 IEnumerable 与 IEnumerator 自定义集合
// 实现 IEnumerable 接口
public class Week : IEnumerable
{
// 只为取得 IEnumerator
public IEnumerator GetEnumerator()
{
return new WeekEnumerator();
}
}
// 实现 IEnumerator 接口
public class WeekEnumerator : IEnumerator
{
// 和第一个示例中一样
...
}
由于 yield 帮助生成 IEnumerator 类型,所以可以使用 yield 来简化自定义集合的定义
// 只需要实现 IEnumerable 接口,通过 yield 语法糖生成 IEnumerator
public class Week : IEnumerable
{
string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
public IEnumerator GetEnumerator()
{
for (int i = 0; i < days.Length; i++)
{
yield return days[i];
}
}
}
本文深入探讨C#中的迭代器概念,包括IEnumerator接口的实现,yield关键字的使用,以及如何利用IEnumerable接口简化循环访问。通过具体代码示例,解析自定义集合的迭代逻辑。
221

被折叠的 条评论
为什么被折叠?



