zoukankan      html  css  js  c++  java
  • 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();



  • 相关阅读:
    httpclient 发送 json数据,微信security.msgSecCheck,
    win10 输入法,添加美式键盘,调整顺序
    activiti与spring的集成
    spring 中实例化Bean的三种方式
    工作流activiti的HelloWorld
    工作流Activiti的前置准备工作。
    Eclipse中配置约束(DTD,XSD)
    微信开发中,本地缓存,不同步的问题
    微信开发中碰到的坑,json传值,前台遍历json对象,跨页面转值,navigate层级限制
    用pageInfo对List手工分页
  • 原文地址:https://www.cnblogs.com/ArtofDesign/p/3612533.html
Copyright © 2011-2022 走看看