IEnumerable实践应用

1.集合想要支持foreach方式遍历,需要返回一个迭代器(IEnumerator),foreach会自动调用迭代器的状态迁移(MoveNext()、Curent、Reset())

#region Assembly mscorlib.dll, v4.0.0.0
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll
#endregion

using System;
using System.Runtime.InteropServices;

namespace System.Collections
{
    // Summary:
    //     Supports a simple iteration over a nongeneric collection.
    [ComVisible(true)]
    [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
    public interface IEnumerator
    {
        object Current { get; }

        bool MoveNext();

        void Reset();
    }
}

2.IEnumerable接口定制了foreach的需求

#region Assembly mscorlib.dll, v4.0.0.0
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll
#endregion

using System.Runtime.InteropServices;

namespace System.Collections
{
    // Summary:
    //     Exposes the enumerator, which supports a simple iteration over a non-generic
    //     collection.
    [ComVisible(true)]
    [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
    public interface IEnumerable
    {
        [DispId(-4)]
        IEnumerator GetEnumerator();
    }
}

3.类似于List的列表定义如下:

    /// <summary>
    /// 列表
    /// </summary>
    class MyList : ArrayList, IEnumerable<object>
    {

        // 迭代器返回  
        public IEnumerator<object> GetEnumerator()
        {
            return new MyListEnumerator(this);
        }

        /// <summary>
        /// 1.由于IEnumerable<T>继承自IEnumerable,因此必须实现其方法
        /// 2.由于已经存在同名方法,因此需要显示实现
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            //return GetEnumerator(); // IEnumerator是IEnumerator<T>的基类  
            return null;
        }
    }

    /// <summary>
    /// 为列表定制的迭代器
    /// </summary>
    class MyListEnumerator : IEnumerator<object>
    {
        private int current = -1;
        private MyList _mylist;

        public MyListEnumerator(MyList mylist)
        {
            _mylist = mylist;
            current = _mylist == null || _mylist.Count == 0 ? -1 : 0;
        }

        public bool MoveNext()
        {
            current++;
            return _mylist != null && _mylist.Count > current;
        }

        object IEnumerator<object>.Current
        {
            get
            {
                if (_mylist != null && _mylist.Count > current) return _mylist[current];
                return null;
            }
        }
        // 1.由于IEnumerable<out T>继承自IEnumerable,因此必须实现其方法
        // 2.由于已经存在同名方法,因此需要显示实现
        object IEnumerator.Current
        {
            get
            {
                //if (_mylist != null && _mylist.Count > current)return _mylist[current];
                return null;
            }
        }

        public void Reset()
        {
            current = _mylist == null || _mylist.Count == 0 ? -1 : 0;
        }

        // IEnumerator<T>继承了IDisposable,为了遍历完后清理状态,所以需要实现该方法  
        // 该方法在foreach循环完毕后自动调用  
        public void Dispose() { }
    }

4.IEnumerator作为迭代器,源于底层编程语言指针的启发;

引用类型不同于值类型的一个重要特点就是用到的时候才会进行真正的处理

.Net中yield关键字对此有很好的支持,以下举例说明:

       static void Main(string[] args)
        {
            var list = GetStrings(5);
            foreach (var item in list)
            {
                Console.WriteLine(item);
            }

            list = GetStrings(10);
            foreach (var item in list)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }运行结果:

        /// <summary>
        /// 1.yield return将单次运算结果放入IEnumerable集合中
        /// 2.yield break中断当前迭代器的作用域
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public static IEnumerable<string> GetStrings(int length = 0)
        {
            for (int i = 0; i < length; i++)
            {
                if (i < 5)
                {
                    yield return string.Format("第{0}次调用", i);
                }
                else
                {
                    yield break;
                }
            }
            Console.WriteLine("yield break之后在迭代作用域内的代码不会再被执行");
        }

补充:上面GetStrings传统上很多人习惯如下写法,但是这样做的时间开销是n*m,其中n为待运算列表长度,m为第一次遍历长度,这就是为什么上面强调用到的时候才会进行真正的处理

 public static List<string> GetStrings(int length = 0)
        {
            var result = new List<string>();
            for (int i = 0; i < length; i++)
            {
                if (i < 5)
                {
                    result.Add(string.Format("第{0}次调用", i));
                }
            }
            return result;
        }
时间: 2024-10-12 19:41:22

IEnumerable实践应用的相关文章

C#编程实践–帮老婆计算产假方案

摘要 今天中午午休时,和老婆聊天,老婆还过几天就要请产假了,她在网上问我让我帮她数一下该怎么请假最划算,老婆是个会过日子的人,面对此种要求我当然义不容辞,不过想到这个问题我的第一反应是:这个怎么可以用数的呢?于是,我开始去了解2014年上海市最新的产假政策规定,大致概况如下:“产假加上晚育假一共128天,其中前面98天是正常产假,其中已经包括国家法定节日和双休日,后面30天是晚育假,只包含双休日,不包含国家法定节日,也就是说遇到国家法定节日则假期往后顺延”,注意黑体粗字描述,可以知道这里面的精打

EntityFramework之领域驱动设计实践

EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领域驱动设计实践 (二):分层架构 EntityFramework之领域驱动设计实践 (三):案例:一个简易的销售系统 EntityFramework之领域驱动设计实践 (四):存储过程 - 领域驱动的反模式 EntityFramework之领域驱动设计实践 (五):聚合 EntityFramewor

MVC项目实践,在三层架构下实现SportsStore-01

SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管理.图像上传......是不错的MVC实践项目,但该项目不是放在多层框架下开发的,离真实项目还有一段距离.本系列将尝试在多层框架下实现SportsStore项目,并用自己的方式实现一些功能. 本篇为系列第一篇,包括: ■ 1.搭建项目■ 2.卸载Entity Framework组件,并安装最新版本■ 3.使用

Entity Framework 实践系列 —— 搞好关系 - 单相思(单向一对一,one-to-one)

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 原以为躲入代码世界,就可以不用搞关系,哪知"关系无处不在".写代码多年之后,终于明白"面向对象的关键是搞好对象之间的关系".而Entity Framework作为ORM中的明日之星,首当其冲的使命就是配合对象搞好关

MVC项目实践,在三层架构下实现SportsStore-01,EF Code First建模、DAL层等

http://www.cnblogs.com/darrenji/p/3809219.html 本篇为系列第一篇,包括: ■ 1.搭建项目■ 2.卸载Entity Framework组件,并安装最新版本■ 3.使用EF Code First创建领域模型和EF上下文■ 4.三层架构设计    □ 4.1 创建DAL层        ※ 4.1.1 MySportsStore.IDAL详解        ※ 4.1.2 MySportsStore.DAL详解 1.搭建项目 MySportsStore.

[转]ASP.NET MVC 4 最佳实践宝典

原文:http://www.cnblogs.com/sonykings/archive/2013/05/30/3107531.html ASP.NET MVC最佳实践 本文档提供了一套旨在帮助创建最佳优化ASP.NET MVC应用程序的 开发人员编码准则. 当然,由您来选择这些优化准则. 模型的建议 Model是定义业务领域相关的对象,应该包含业务逻辑(对象如何动作和关联),验证逻辑(验证对象的有效值),数据逻辑(数据对象如何持久化),和会话逻辑(跟踪用户状态). 创建独立的Model项目,在A

领域驱动设计实践上篇

一.前言 领域驱动设计的概念最早是由著名的建模专家Eric Evans在2004年发表的著名书籍 Domain-Driven Design –Tackling Complexity in the Heart of Software(中文译名:领域驱动设计 2006年3月清华出版社译本,或称 Domain Driven-Design architecture [Evans DDD]).园子里有很多人早已将其实践并应用,关于其要素.特点不再赘述,很多人在技术选型时想用它但又怕驾驭不了它,无非是没有真

MVC项目实践,在三层架构下实现SportsStore-03,Ninject控制器工厂等

SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管理.图像上传......是不错的MVC实践项目,但该项目不是放在多层框架下开发的,离真实项目还有一段距离.本系列将尝试在多层框架下实现SportsStore项目,并用自己的方式实现一些功能. 本篇为系列第三篇,包括: ■ 5.自定义Ninject控制器工厂■ 6.项目的第一次运行 5.自定义Ninject控制

MVC项目实践,在三层架构下实现SportsStore-05,实现导航

SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管理.图像上传......是不错的MVC实践项目,但该项目不是放在多层框架下开发的,离真实项目还有一段距离.本系列将尝试在多层框架下实现SportsStore项目,并用自己的方式实现一些功能. 本篇为系列第五篇,包括: ■ 8.导航 8.导航 创建NavController,派生于BaseController: