2021年了,`IEnumerator`、`IEnumerable`还傻傻分不清楚?
IEnumerator、IEnumerable这两个接口单词相近、含义相关,傻傻分不清楚。
入行多年,一直没有系统性梳理这对李逵李鬼。
最近本人在怼着why神的《其实吧,LRU也就那么回事》,方案1使用数组实现LUR,手写算法涉及这一对接口,借此机会本次覆盖这一对难缠的冤家。
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的GetEnumerator方法的返回值转换为IEnumerator接口。
从英文词根上讲:
IEnumerator接口代表了枚举器,里面定义了枚举方式;
IEnumerable接口代表该对象具备了可被枚举的性质。
总之,IEnumerable的使用要求类实现IEnumerator。如果您想提供对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属性的get访问器
2021年了,`IEnumerator`、`IEnumerable`还傻傻分不清楚?的更多相关文章
- JS魔法堂:属性、特性,傻傻分不清楚
一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...
- Java:接口和抽象类,傻傻分不清楚?
01. 来看网络上对接口的一番解释: 接口(英文:Interface),在 Java 编程语言中是一个抽象类型,是抽象方法的集合.一个类通过继承接口的方式,从而来继承接口的抽象方法. 兄弟们,你们怎么 ...
- [转帖]十分钟快速理解DPI和PPI,不再傻傻分不清!
十分钟快速理解DPI和PPI,不再傻傻分不清! https://baijiahao.baidu.com/s?id=1605834796518990333&wfr=spider&for= ...
- 【华为敏捷/DevOps实践】7. 敏捷,DevOps,傻傻不分清楚【华为云技术分享】
文:姚冬(华为云DevCloud首席技术布道师,资深DevOps与精益/敏捷专家,金融解决方案技术Leader,中国DevOpsDays社区核心组织者) 前言 敏捷是什么?DevOps是什么?两者有什 ...
- 傻傻分不清之 Cookie、Session、Token、JWT
傻傻分不清之 Cookie.Session.Token.JWT 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打 ...
- Shell中傻傻分不清楚的TOP3
Shell中傻傻分不清楚的TOP3 发布文章 近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Comm ...
- URI与URL傻傻分不清楚?
前言 总所周知,缓存是解决Http1.1协议传输性能的问题中最主要的手段. 缓存既可以存在于浏览器上,也可以存在于服务器中. 而影响缓存的Http头部有很多,其中Cache-Control是比较重要的 ...
- 【jvm】08-垃圾回收器那么多傻傻分不清?
[jvm]08-垃圾回收器那么多傻傻分不清? 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点 ...
- JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文带你厘清个中曲直,给你个选择SpringDataJPA的理由!
序言 Spring Data JPA作为Spring Data中对于关系型数据库支持的一种框架技术,属于ORM的一种,通过得当的使用,可以大大简化开发过程中对于数据操作的复杂度. 本文档隶属于< ...
随机推荐
- Flutter开发实战笔记
下载 https://flutter.cn/docs/get-started/install/macos#get-sdk 配置环境变量 export PATH="$PATH:[PATH_TO ...
- ripple Failed to load resource: the server responded with a status of 404 (Not Found)
在VS2015中使用Cordova + typescript开发中,遇到个问题. 在javascript console 中提示: Failed to load resource: the serve ...
- git 常用命令--超实用
git命令行常用操作 1.配置ssh key git config --global user.name 'git用户名' git config --global user.email '邮箱地址' ...
- 自定义radio、checkbox的样式
input标签中的radio和checkbox是很表单中常用的类型,大多时候,默认样式并不能满足我们的需求,所以有了此篇. 自定义样式,由此开启: html: <div class=" ...
- mysql主从同步错误
一.主从同步报错 mysql> show slave status\G; *************************** 1. row ************************* ...
- Leetcode——练习
平时没事刷刷Leetcode,还办了个年会员.为了自己150刀.为了自己的大脑投资,从不差钱儿.刷刷题能练习coding,此外看一些别人的优秀的答案,能增长见解.大家共同努力,共勉. 十.Google ...
- CentOS 7 mini版本安装后必须要做的几件事
Linux家族非常的庞大,诸如Debian.Ubuntu.RedHat.CentOS.ArchLinux.Gentoo,甚至还有国内比较有名的Deepin,都是Linux家族闪耀的明星.根据实际需求涉 ...
- 网络编程-python实现-UDP(1.1.2)
@ 目录 1.UDP是什么 2.代码实现 1.UDP是什么 Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol).UDP ...
- Python制作折线图
利用python的第三方包Pygal制作简单的折线图. 申明:本文仅供学习交流使用.源码大部分来自<python编程从入门到实践>:如有侵权,请联系我删除. 1 #!usr/bin/env ...
- ASP.NET Core 中间件 自定义全局异常中间件以及 MVC异常过滤器作用
中间件是一种装配到应用管道以处理请求和响应的软件. 每个组件: 选择是否将请求传递到管道中的下一个组件. 可在管道中的下一个组件前后执行工作. 请求委托用于生成请求管道. 请求委托处理每个 HTTP ...