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

场景:
假如一个集合中有一百万条数据,我们只想要前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(历届)昆明31...   随着全省参统企业退休人员基本养老金的调整,截至目前,我市31.2万名企业退休人员已经领取了1-3...
昆明农村教师每月可获500元补...   【教师薪资行情】新学年开学半月,许多农村的孩子们又恢复了早早起床,背着书包结伴走过山路去学校的生...
最新或2023(历届)福布斯中...   10月28日最新消息,福布斯中文网今天发布了最新或2023(历届)中国富豪榜,BAT三大互联网巨...
福布斯中国富豪榜最新或2023...   今日,网上公布最新或2023(历届)中国富豪榜。榜单显示,阿里巴巴集团董事会主席马云取代万达集团...