C# yield return详解。
创始人
2025-05-31 05:51:14
0

场景:
假如一个集合中有一百万条数据,我们只想要前1000条。

错误代码示范

     foreach (var c in GetCustomers(1000000)){if (c.Id < 1000){Console.WriteLine($"ID:{c.Id},Name:{c.Name}");}else {break;}}Console.Read();static IEnumerable GetCustomers(int count){List listcustomers = new List();for (int i = 0; i < count; i++){var customer = new Customer{Id = i,Name = $"Name{i}"};listcustomers.Add(customer);}return listcustomers;}

这种代码有个很大的错误就是,我们明明只需要1000条数据,它却创建了一百万条数据,极大的浪费了内存。

正确示范,使用yield return关键字。

   foreach (var c in GetCustomersYield(1000000)){if (c.Id < 1000){Console.WriteLine($"ID:{c.Id},Name:{c.Name}");}else {break;}}Console.Read();static IEnumerable GetCustomersYield(int count) {for (int i = 0; i < count; i++){yield return new Customer { Id=i,Name=$"Name{i}"};}}

通过运行代码可以看到,GetCustomersYield(1000000)不会立刻去创建实体,甚至代码不会直接运行GetCustomersYield 这个方法,他会先走循环,然后根据循环体需求,去创建数据。yield return底层是对迭代器的实现。所以方法可以直接返回IEnumerable 类型,除非数据必须使用,不然yield return返回的对象是不会被立即创建的,有点懒加载的意思。实际上yield return返回的并不是数据,而是数据的迭代。通过多次叠加,其实循环遍历的结果,就是迭代器的集合。这样使用yield return关键字就只创建出来了1000条数据,大大的节省了内存开销。

接下来我们对 上面的2个代码 示例做下性能对比 。

Nuget 下载BenchmarkDotNet跑分工具。
单独创建一个BenchmarkTest类去跑

[MemoryDiagnoser]public class BenchmarkTest{[Benchmark]public void ProcessCustomer() {var customers = GetCustomers(1000000);foreach (var c in customers){if (c.Id < 1000){Console.WriteLine($"ID:{c.Id},Name:{c.Name}");}else{break;}}}[Benchmark]public void ProcessCustomerYield(){var customers = GetCustomersYield(1000000);foreach (var c in customers){if (c.Id < 1000){Console.WriteLine($"ID:{c.Id},Name:{c.Name}");}else{break;}}}static IEnumerable GetCustomers(int count){List listcustomers = new List();for (int i = 0; i < count; i++){var customer = new Customer{Id = i,Name = $"Name{i}"};listcustomers.Add(customer);}return listcustomers;}static IEnumerable GetCustomersYield(int count){for (int i = 0; i < count; i++){yield return new Customer{Id = i,Name = $"Name{i}"};}}}

切记类上和方法上要加上对应的特性。

主方法调用

  static void Main(string[] args){var sumery =  BenchmarkRunner.Run();}

Benchmark只能在Release版本进行跑分,打开项目根目录。然后文件夹上 cmd
输入如下命令生成Release

dotnet build -c Release

在这里插入图片描述

拿到画线的地址,执行如下命令

dotnet D:\test\集合操作\集合操作\bin\Release\net5.0\集合操作.dll

等待跑分结果,如图:
在这里插入图片描述

C#课程欢迎留言或者私聊。

相关内容

热门资讯

最新或2023(历届)作文千手...  【篇一】  21个聋哑人,她们在舞台上尽情挥洒,她们在残缺中追求完美,在无声中激荡生命。她们在娇媚...
[SwiftUI]GroupB... 代码: import SwiftUIstruct MPMineView: View {...
甲午大海战观后感2000字 甲...   【篇一】  坐在电脑前看《一八九四·甲午大海战》时,我是怀着十分忐忑的心情的,因为已经预知那段清...
风雨哈佛路观后感500字 风雨...   【篇一】  这部电影我看了很受触动,女主人公经历了常人不敢想象的成长道路,最终实现了梦想,走进了...
最新或2023(历届)感动中国...  【篇一】  "感动你我,感动中国,这世界有爱才转动。感动你我,感动中国,这世界有爱才永恒。"当《感...
历史文献纪录片信仰观后感 历史... 【篇一】  曾经,在念大学的时候,"信仰"对我而言是很空、很大,虚无缥缈,是个看不见、摸不着的东西。...
【ACL】访问控制列表 文章目录1.访问控制列表1.1 ACL概述1.2 ACL在接口的应用方向2.ACL的工作原理2.1 ...
优秀班主任主要事迹10篇汇总 ... 篇一:  本人自2009年参加工作以来,一直担任班主任工作,本人在班级管理、教学和德育工作方面均表现...
最新或2023(历届)初中模范... 篇一:优秀班主任先进事迹材料  我从事教育教学工作二十一年了,多年来,我和广大教师一样,热爱教育事业...
最新或2023(历届)县优秀班...   爱岗敬业呕心化春雨 倾情撑蓝天  记玉龙县优秀教师 xxx  xxx,女,纳西族,xxx年xx月...
最新或2023(历届)优秀班主...   篇一:优秀班主任先进事迹  ***,男,汉族,1973年8月出生于安徽明光市,现为经济管理学院综...
电影南京南京观后感大全 关于电...  【篇一】  5.1号走进莱蒙的东方国际影城观看这部期待了很久的电影南京南京,一定要去看这个片子原因...
Python tkinter ... *18.2.23 dchars(args) *args传递的参数有3个: ࿰...
2021年瑶海区信息学初中组 2021年瑶海区信息学初中组 1.完全立方数(cube) 问题描述 小瑶酷爱数学,这两天在研究完全立...
优秀班主任推荐材料表材料 优秀... 我叫,自担任班主任以来,关爱学生,爱岗敬业,尽职尽责,严于律己,班级教育教学管理 成绩 突出.特别....
乡镇妇联主席先进事迹 乡镇妇联...  篇一:  ***,最新或2023(历届)12月任**镇妇联主席.三年来,她以加强理论和业务学习为立...
最新或2023(历届)先进基层... 社区先进基层党组织事迹材料  桥西社区自创先争优活动开展以来,社区党总支从广大居民需求出发,主打文化...
脱贫攻坚主题党日活动方案 牢记...  今年10月17日,是我国第3个扶贫日,也是第24个国际消除贫困日。推进脱贫攻坚是深入扎实持久开展“...
4年功能测试,我一进阶pyth... 目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目...
四月学校支部主题党日活动方案 ...  【四月学校支部主题党日活动方案一】  各支部:  根据郧学组办发〔最新或2023(历届)〕3 号文...