(转载)先说IEnumerable

2024-05-06 06:48
文章标签 转载 ienumerable 先说

本文主要是介绍(转载)先说IEnumerable,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文链接:https://www.cnblogs.com/zhaopei/p/5769782.html

先说IEnumerable,我们每天用的foreach你真的懂它吗?

阅读目录

  • 自己实现迭代器
  • yield的使用
  • 怎样高性能的随机取IEnumerable中的值

我们先思考几个问题:

  1. 为什么在foreach中不能修改item的值?
  2. 要实现foreach需要满足什么条件?
  3. 为什么Linq to Object中要返回IEnumerable?

接下来,先开始我们的正文。

自己实现迭代器

.net中迭代器是通过IEnumerable和IEnumerator接口来实现的,今天我们也来依葫芦画瓢。

首先来看看这两个接口的定义:

并没有想象的那么复杂。其中IEnumerable只有一个返回IEnumerator的GetEnumerator方法。而IEnumerator中有两个方法加一个属性。

接下来开发画瓢,我们继承IEnumerable接口并实现:

下面使用原始的方式调用:

有朋友开始说了,我们平时都是通过foreache来取值的,没有这样使用过啊。好吧,我们来使用foreach循环:

为什么说基本上是等效的呢?我们先看打印结果,在看反编译代码。

由此可见,两者有这么个关系:

我们可以回答第一个问题了“为什么在foreach中不能修改item的值?”:

我们还记得IEnumerator的定义吗

 

接口的定义就只有get没有set。所以我们在foreach中不能修改item的值。

我们再来回答第二个问题:“要实现foreach需要满足什么条件?”:

必须实现IEnumerable接口?NO

我们自己写的MyIEnumerable删掉后面的IEnumerable接口一样可以foreach(不信?自己去测试)。

所以要可以foreach只需要对象定义了GetEnumerator无参方法,并且返回值是IEnumerator或其对应的泛型。细看下图:

也就是说,只要可以满足这三步调用即可。不一定要继承于IEnumerable。有意思吧!下次面试官问你的时候一定要争个死去活来啊,哈哈!

yield的使用

你肯定发现了我们自己去实现IEnumerator接口还是有些许麻烦,并且上面的代码肯定是不够健壮。对的,.net给我们提供了更好的方式。

你会发现我们连MyIEnumerator都没要了,也可以正常运行。太神奇了。yield到底为我们做了什么呢?

好家伙,我们之前写的那一大坨。你一个yield关键字就搞定了。最妙的是这块代码:

这就是所谓的状态机吧!

我们继续来看GetEnumerator的定义和调用:

我们调用GetEnumerator的时候,看似里面for循环了一次,其实这个时候没有做任何操作。只有调用MoveNext的时候才会对应调用for循环:

现在我想可以回答你“为什么Linq to Object中要返回IEnumerable?”:

因为IEnumerable是延迟加载的,每次访问的时候才取值。也就是我们在Lambda里面写的where、select并没有循环遍历(只是在组装条件),只有在ToList或foreache的时候才真正去集合取值了。这样大大提高了性能。

如:

这个时候得到了就是IEnumerable对象,但是没有去任何遍历的操作。(对照上面的gif动图看)

什么,你还是不信?那我们再来做个实验,自己实现MyWhere:

现在看到了吧。执行到MyWhere的时候什么动作都没有(返回的就是IEnumerable),只有执行到ToList的时候才代码才真正的去遍历筛选。

这里的MyWhere其实可以用扩展方法来实现,提升逼格。(Linq的那些查询操作符就是以扩展的形式实现的)[了解扩展方法]。

怎样高性能的随机取IEnumerable中的值

原文链接:https://www.cnblogs.com/zhaopei/p/5769782.html

觉得写的真的很好!!

这篇关于(转载)先说IEnumerable的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/963680

相关文章

【转载】 symfony 生成实体类命令

原作者地址:https://www.it603.com/article/88.html 参考文章: https://symfony.com/doc/current/doctrine/reverse_engineering.html How to Generate Entities from an Existing Database https://www.jianshu.com/p/75fc

Spring 学习转载

最近没什么实质性的工作,正好有点时间,就想学学别人的代码。也看过一点源码,算是有了点阅读的经验,于是下定决心看下spring这种大型的项目的源码,学学它的设计思想。   手码不易,转载请注明:xingoo   这篇博文你可以了解到:   1 Spring jar包以及源码使用   2 简单的spring运行示例   3 利用断点调试程序,如何快速的阅读程序【快捷键等的使用】   这次阅

ajax+json+Struts2实现list传递(转载)

一、首先需要下载JSON依赖的jar包。它主要是依赖如下:       json-lib-2.2.2-jdk15       ezmorph-1.0.4       commons-logging-1.0.4       commons-lang-2.4       commons-collections-3.2.1       commons-beanutils      二、

[转载]细说傅里叶变换

原文地址:[转载]细说傅里叶变换 作者:小腹黑zju 原文出处:http://blog.163.com/niujiashu@126/blog/static/1002930422011102501211199/   一、傅立叶变换的由来 关于傅立叶变换,无论是书本还是在网上可以很容易找到关于傅立叶变换的描述,但是大都是些故弄玄虚的文章,太过抽象,尽是一些让人看了就望而生畏的公式的罗列

转载 | 认知推理:从图表示学习和图神经网络的最新理论看AI的未来

近年来,图表示学习(Graph Embedding)和图神经网络(Graph Neural Network, GNN)成为网络数据分析与应用的热点研究问题,其特点是将深度神经网络技术用于网络结构的建模与计算,诞生了以 DeepWalk、LINE 和 node2vec 为代表的图表示学习技术,以 GCN 为代表的图神经网络,能够利用分布式表示方案实现对网络中的节点、边及其附带的标签、属性和文本等信息

【转载】TIOBE 编程指数 6 月排行榜公布,vb.net排第九

原文地址:https://baijiahao.baidu.com/s?id=1801368030428902126&wfr=spider&for=pc IT之家 6 月 9 日消息,TIOBE 编程社区指数是一个衡量编程语言受欢迎程度的指标,评判的依据来自世界范围内的工程师、课程、供应商及搜索引擎,今天 TIOBE 官网公布了 2024 年 6 月的编程语言排行榜,IT之家整理如下: Pyt

Qt 之 qt5安装好后更新添加组件(转载)

QT的组件管理软件并没有在开始菜单或者桌面添加快捷方式(5.9版本),也没有在代码编辑界面设置相关的选项,藏的比较深,因此我被坑了很多次(之前如果要添加组件,只能选择卸载了重装) 在被坑了多次之后,在一次偶然的机会,我在QT安装目录发现了QT的组件管理软件MaintenanceTool 怀着无比激动的心情,我选择“添加或移除组件”点了下一步,结果mmp,提示“要继续此操作,至少需要一个有效

QML 圆角矩形 radius clip 对子组件无效的问题解决方法(转载)

原文链接:https://blog.csdn.net/Likianta/article/details/110703819 本文实现前后效果对比: 正文 根据官方的描述, 考虑到性能表现, 父组件的 radius, clip 对子组件是无效的, 也就是说如果外部矩形设置圆角矩形, 对内部矩形的裁剪是无效的, 如下图所示: 下面介绍一种最简单的方案, 使用 layer 属性来实现圆角区

Qt 之 QML中动态创建组件(同步/异步)的方法 (转载)

原文链接:https://blog.csdn.net/u011283226/article/details/98978828 【写在前面】 在 QML 中想要动态创建组件,一般有两种方法: 1、使用 Loader。 2、使用 JavaScript:Qt.createComponent() / Qt.createQmlObject()。 当然,这里不仅会介绍他们的一般用法,还有如何使用它们

非常容易理解的KMP字符串匹配算法转载过来记录一下

https://www.cnblogs.com/maybe2030/p/4633153.html 写的非常明白,留个记录,需要的可以直接进去看 代码记录,getNext就是算那个“部分匹配值”编码的序列,也就是该文中的这个图 查询的直接可以根据这个编码进行跳跃式的查询减少多余匹配的消耗,移动位数 = 已匹配的字符数 - 对应的部分匹配值,下面对应代码记录下“部分匹配值”的计算过程:搜索词是