登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
导读
排行榜
资讯
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
写博客
小组
VIP申请
VIP网盘
网盘
联系我们
发帖说明
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
先说IEnumerable,我们每天用的foreach你真的懂它吗? ...
先说IEnumerable,我们每天用的foreach你真的懂它吗?
[ 复制链接 ]
站竣凰
2025-5-29 00:11:43
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
我们先思考几个问题:
为什么在foreach中不能修改item的值?
要实现foreach需要满足什么条件?
为什么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中的值
这段代码来源《深入理解C#》,个人觉得非常妙。贴出来给大家欣赏哈。
结束:
demo下载:http://pan.baidu.com/s/1dE94c1b
接下篇:《再讲IQueryable,揭开表达式树的神秘面纱》
本文以同步至《C#基础知识巩固系列》
来源:新程序网络收集,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
先说
IEnumerable
我们
每天
用的
相关帖子
在自动化测试时,Python常用的几个加密算法,你有用到吗
Debian 12/13可用的华宇拼音输入法
从一次分表实践谈起:我们真的需要复杂的分布式ID吗?
有用的包 #Python
vue 常用的 gantt 甘特图组件推荐
最新常用的js跳转代码
我们提供了这些企业和开发者所需的热门技术栈教程
10GB vs 600MB:我们弃用 GitLab,选择了这个轻量级神器
LLM 工具调用的范式演进与认知模型集成
再推荐 10 个低调但非常实用的 PHP 包
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
安全
在自动化测试时,Python常用的几个加密算法,你有用到吗
2
870
厂潺
2025-11-18
安全
Debian 12/13可用的华宇拼音输入法
4
751
锺冰洁
2025-11-20
业界
从一次分表实践谈起:我们真的需要复杂的分布式ID吗?
4
1064
杭环
2025-11-20
业界
有用的包 #Python
4
900
茅断卉
2025-12-07
代码
vue 常用的 gantt 甘特图组件推荐
2
710
柴古香
2025-12-09
代码
最新常用的js跳转代码
2
30
新程序
2025-12-11
安全
我们提供了这些企业和开发者所需的热门技术栈教程
0
113
佴莘莘
2025-12-13
业界
10GB vs 600MB:我们弃用 GitLab,选择了这个轻量级神器
1
470
僭墙覆
2025-12-13
业界
LLM 工具调用的范式演进与认知模型集成
1
373
万妙音
2025-12-16
业界
再推荐 10 个低调但非常实用的 PHP 包
0
346
富账慕
2025-12-19
回复
(2)
雌鲳签
2025-12-8 22:03:51
回复
使用道具
举报
照妖镜
程序园永久vip申请,500美金$,无限下载程序园所有程序/软件/数据/等
感谢分享
缀访
2025-12-11 08:52:39
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢分享
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
浏览过的版块
安全
签约作者
程序园优秀签约作者
发帖
站竣凰
2025-12-11 08:52:39
关注
0
粉丝关注
29
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
3934307807
991124
anyue1937
9994891
kk14977
6845357
4
xiangqian
638210
5
韶又彤
9997
6
宋子
9982
7
闰咄阅
9993
8
刎唇
9993
9
俞瑛瑶
9998
10
蓬森莉
9951
查看更多
今日好文热榜
772
AI Agent详解
977
Buildah 简明教程:让镜像构建更轻量,告别
603
OceanBase 在滴滴大规模运维经验以及新功能
972
[CSS+]HTML Learn Data Day 2
94
掌握相关性分析:读懂数据间的“悄悄话”
136
嵌入式UI框架-抗锯齿画圆弧算法
935
嵌入式UI框架的渐变原理、渐变算法
217
日本股票 API 对接实战指南(实时行情与 IP
561
解决Docker磁盘空间告急:认识并清理“悬空
393
别再只会算直线距离了!用“马氏距离”揪出
524
企业进行信息化后,一定会提高效率吗?真相
515
n8n整合ffmpeg
492
从random随机数看验证码重复数字
523
OceanBase 向量索引优化指南
232
Vue2中能否实现输入中文自动转化为拼音, 且
753
从项目成果到职业晋升:项目经理年终总结的
452
JS逆向-混淆加密-识别&还原-Eval&JSFuck&JS
937
2025年上海防水补漏谁家强?长三角标杆企业
615
正式接入DeepSeek-V3.2,国产AI“双剑合壁
399
守嘉陪诊师培训报名热潮引关注 独家实习机