• C#枚举器:foreach语句、IEnumerable、IEnumerator以及yield return (二)


    using System;
    using System.Collections;

        关于使用IEnumerable、IEnumerator以及yield return来实现对foreach语句的支持,参见:《C#枚举器:foreach语句、IEnumerable、IEnumerator以及yield return (一)》

        本文主要是分析一下foreach语句本身:

    foreach (var item in collection)
    {
        //do someth  
    }

        foreach语句要求遍历的对象collection实现GetEnumerator方法(这个方法定义在IEnumerable中),所以foreach语句工作时其实是转化成了如下语句来迭代collection中的每个元素的:

    IEnumerator enumerator = colloction.GetEnumerator();
    while(enumerator.MoveNext())
    {
        var item = enumerator.Current;
        //do something
    }

        事实上,这里的collection可以替换成任何实现了GetEnumerator()方法的对象,或者一个表达式且该表达最终返回一个实现了GetEnumerator()方法的对象,比如

    //假设myArray.Reverse()返回一个继承自IEnumerable接口的对象,或者实现了GetEnumerator()方法的对象
    foreach (var item in myArray.Reverse())
    {
        //do something
    }

        了解到这一点后,我们可以按照自己的想法去充分挖掘foreach迭代的用法,例如

    public class Names:IEnumerable
    {
        string[] names = { "David", "Peter", "Kunta", "Linda", "Bob" };
        //基本迭代
        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < 5; i++)
            {
                yield return names[i];
            }
        }
        //逆序迭代
        public IEnumerable Reverse()
        {
            for (int i = 4; i >= 0; i--)
            {
                yield return names[i];
            }
        }
        //部分迭代
        public IEnumerable Subset(int startIndex, int length)
        {
            for (int i = startIndex; i < startIndex + length; i++)
            {
                yield return names[i];
            }
        }
    }
    
    public class TestNames
    {
        public static void Test()
        {
            var names = new Names();
            foreach (var name in names)//基本迭代的调用
            {
                Console.WriteLine(name);
            }
            foreach (var name in names.Reverse())//逆序迭代的调用
            {
                Console.WriteLine(name);
            }
            foreach (var name in names.Subset(2,2))//部分迭代的调用
            {
                Console.WriteLine(name);
            }
            Console.ReadKey();
        }
    }

        按照前面的所说的:

        ①第一个基本迭代的对象是names,foreach会最终去调用names.GetEnumerator(),这种是我们定义在Names类中的方法;

        ②第二个逆序迭代的对象是names.Reverse(),该方法返回IEnumerable接口,肯定是实现了GetEnumerator()方法的,因此foreach语句会最终去调用names.Reverse().GetEnumerator(),而这里这个GetEnumerator()并不是我们在Names类中实现的方法,而是yield return语句自动生成的;

        ③第三个与第二个一样,foreach语句最终会调用names.Subset(2, 2).GetEnumerator();



  • 相关阅读:
    手机游戏怎么独占世界手游鳌头
    游戏开发商是如何做到每日进帐410万美元的?
    [手游新项目历程]-48-svn分支开发与主干合并
    三国武将所带兵种
    Supercell:靠两款手游如何做到30亿美金市值?
    理财投资这需要知道的50个真相
    [手游新项目历程]-49-性能分析
    [手游新项目历程]-50-Mysql的大字段问题(数据库执行错误: Error=1118, Reason=Row size too large (> 8126))
    三国杀
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/ArtofDesign/p/3612533.html
Copyright © 2020-2023  润新知