如何在C#的foreach循环中调用GetEnumerator方法?

时间:2016-10-30 11:34:34

标签: c# collections foreach iterator

我正在经历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");

1 个答案:

答案 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()