我正在经历Iterator模式,当我在示例代码中找到逻辑时,我有点困惑
class MonthCollection : IEnumerable
{
public string[] months = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
public IEnumerator GetEnumerator()
{
// Generates values from the collection
foreach (string element in months)
yield return element;
}
}
static void Main()
{
MonthCollection collection = new MonthCollection();
// Consumes values generated from collection's GetEnumerator method
foreach (string n in collection)
Console.Write(n + " ");
Console.WriteLine("\n");
}
在这段代码中,访问Array到字符串的常规方法是在foreach语句中调用这样的month变量
MonthCollection collection = new MonthCollection();
foreach(collection.months中的字符串n){}
但是我无法理解foreach是如何访问的 甚至没有直接调用month变量的集合
MonthCollection collection = new MonthCollection();
foreach(集合中的字符串n){}
更新1
我无法理解的是如何在上述类
中无需调用它来访问变量月份static void Main()
{
MonthCollection collection = new MonthCollection();
// Consumes values generated from collection's GetEnumerator method
foreach (string n in collection.months)
Console.Write(n + " ");
Console.WriteLine("\n");
}
而不是像这样
MonthCollection collection = new MonthCollection();
method
foreach (string n in collection)
Console.Write(n + " ");
Console.WriteLine("\n");
答案 0 :(得分:2)
foreach
循环不需要集合,它只需要一个返回GetEnumerator()
IEnumerator
方法的对象,在您的情况下会带有IEnumerable
实现。
C#编译器产生剩余的“魔法” - 一个隐藏的临时变量来引用枚举器对象,开始枚举的代码,获取每个项目的代码,以及查看枚举何时结束的代码。
在您的情况下,C#依赖于您的实现来使用另一块“魔法” - months
构造来获取yield return
数组的内容。此构造允许您实现GetEnumerator()
而无需为其编写单独的类。构造转换为具有状态机的类,让您从循环的中间“返回”对象,然后重新返回到迭代器请求下一个项目时的位置。
从yield return
返回的对象不必来自集合。您甚至可以将集合中的对象与其他对象混合,例如
public IEnumerator GetEnumerator() {
// Generates values from the collection
foreach (string element in months) {
yield return element + " will start soon!";
yield return element;
yield return element + " has ended.";
}
}
通过实现foreach
的代码间接地 months
循环访问变量GetEnumerator()
。