博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2021年了,`IEnumerator`、`IEnumerable`接口还傻傻分不清楚?
阅读量:4034 次
发布时间:2019-05-24

本文共 2980 字,大约阅读时间需要 9 分钟。

IEnumeratorIEnumerable这两个接口单词相近、含义相关,傻傻分不清楚。

入行多年,一直没有系统性梳理这对李逵李鬼。

最近本人在怼着why神的《》,方案1使用数组实现LRU,手写算法涉及这一对接口,借此时机覆盖这一对难缠的冤家。

IEnumerator

IEnumerator、IEnumerable接口有相似的名称,这两个接口通常也在一起使用,它们有不同的用途。

IEnumerator接口为类内部的集合提供了迭代方式, IEnumerator 要求你实现三个方法:

  • MoveNext方法:该方法将集合索引加1,并返回一个bool值,指示是否已到达集合的末尾。

  • Reset方法:它将集合索引重置为其初始值-1,这会使枚举数无效。

  • Current方法: 返回position位置的当前对象

IEnumerable

IEnumerable接口为foreach迭代提供了支持,IEnumerable要求你实现GetEnumerator方法。

public IEnumerator GetEnumerator(){    return (IEnumerator)this;}

该用哪一个接口?

仅凭以上辞藻,很难区分两个接口的使用场景。

IEnumerator接口定义对类中的集合类型对象的迭代方式

IEnumerable接口允许使用foreach循环进行枚举。

因此IEnumerable接口的GetEnumerator方法会返回一个IEnumerator接口。要实现IEnumerable,你还必须实现IEnumerator

从英文词根上讲:

IEnumerator接口代表了枚举器,里面定义了枚举方式,是名词。
IEnumerable接口代表该对象具备了可被枚举的性质,是形容词。

总之,如果您想提供对foreach的支持,那么就先让对象可枚举,再谈论枚举方式,也就是说实现这两个接口。

最佳实践

  • 在嵌套类中实现IEnumerator,这样你可以创建多个枚举器。

  • 为IEnumerator的Current方法提供异常处理。

    为什么要这么做?
    如果集合的内容发生变化,则reset方法将被调用,紧接着当前枚举数无效,您将收到一个IndexOutOfRangeException异常(其他情况也可能导致此异常)。所以执行一个Try…Catch块来捕获这个异常并引发InvalidOperationException异常, 提示在迭代时不允许修改集合内容。

这也正是我们常见的在foreach 里面尝试修改迭代对象会报InvalidOperationException异常的原因。

下面以汽车列表为例实现IEnumerator IEnumerable接口

using System;using System.Collections;namespace ConsoleEnum{    public class cars : IEnumerable    {        private car[] carlist;          //Create internal array in constructor.        public cars()        {            carlist= new car[6]            {                new car("Ford",1992),                new car("Fiat",1988),                new car("Buick",1932),                new car("Ford",1932),                new car("Dodge",1999),                new car("Honda",1977)            };        }        //private enumerator class        private class  MyEnumerator:IEnumerator        {            public car[] carlist;            int position = -1;            //constructor            public MyEnumerator(car[] list)            {                carlist=list;            }            private IEnumerator getEnumerator()            {                return (IEnumerator)this;            }            //IEnumerator            public bool MoveNext()            {                position++;                return (position < carlist.Length);            }            //IEnumerator            public void Reset()            {                position = -1;            }            //IEnumerator            public object Current            {                get                {                    try                    {                        return carlist[position];                    }                    catch (IndexOutOfRangeException)                    {                        throw new InvalidOperationException();                    }                }            }        }  //end nested class      public IEnumerator GetEnumerator()      {          return new MyEnumerator(carlist);      }    }}

foreach cars的时候,可以明显看到

  • foreach语法糖初次接触可枚举的cars, 实际会访问cars实现的 GetEnumerator()方法,拿到迭代器

  • foreach每次迭代,实际会访问迭代器的Current属性

关注并星标我们

更多干货及最佳实践分享

转载地址:http://ddudi.baihongyu.com/

你可能感兴趣的文章
网络英语 第一章
查看>>
搞笑短信用英文写起来啥样呢……
查看>>
The Relationship Between ZB,NB,SB and LP 第一篇
查看>>
百度vs 谷歌(本来大家都叫它“狗狗”,居然叫谷歌,名字够难听)
查看>>
如何成为编程高手
查看>>
本科生的编程水平到底有多高
查看>>
AngularJS2中最基本的文件说明
查看>>
java/JDK配置环境变量
查看>>
P2S与P2P
查看>>
SOA基础概念【整理中】
查看>>
Web Service概念(废)
查看>>
Tomcat,apache,web服务器,servlet,jsp
查看>>
Web Service概念整理(整理中)
查看>>
人类创造出来的世界——电子世界
查看>>
java可以递归多少次
查看>>
从头开始学习JSP(1)采用MyEclipse和Tomcat运行一个简单的.jsp程序
查看>>
从头开始学习jsp(2)——jsp的基本语法
查看>>
从头开始学习JSP(3)——一些配置
查看>>
html常用标签快速检索
查看>>
使用与或运算完成两个整数的相加
查看>>