我正在使用迭代器模式,当我在示例代码
中发现逻辑时,我感到有点困惑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");
}
在这段代码中,访问数组到字符串的正常方式是在foreach语句
中像这样调用month_variableMonthCollection collection = new MonthCollection();
foreach (string n in collection.months){}
但是我不明白foreach是如何访问的集合,甚至不直接调用months变量
MonthCollection collection = new MonthCollection();
foreach (string n in collection){}
更新1
我不明白的是,在上面的类
中,如果不像这样调用变量months,我怎么能访问它呢?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");
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()
。