对[foreach]的浅究到发现[yield]

简介: 原文:对[foreach]的浅究到发现[yield]  闲来无事,翻了翻以前的代码,做点总结,菜鸟从这里起航,呵呵。 一、List的foreach遍历   先上代码段[1]: 1 class Program 2 { 3 static void Main...
原文: 对[foreach]的浅究到发现[yield]

  闲来无事,翻了翻以前的代码,做点总结,菜鸟从这里起航,呵呵。

一、List的foreach遍历

  先上代码段[1]:

 1  class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             List<string> dayList = new List<string> { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
 6             foreach (var day in dayList)
 7             {
 8                 Console.WriteLine(day);
 9             }
10             Console.ReadKey();
11         }
12     }

  这是我们经常用的,简单明了,这里就不赘述了。

二、对List的浅究

  接着我就产生了疑问,List具有怎样的特性才使得foreach可以对它进行遍历呢?这个遍历是如何实现的?

  下面就来浅究,再上代码段[2]:

 1     public class DaysList<T> : System.Collections.IEnumerable
 2     {
 3         T[] daysArry;
 4         public DaysList(T[] days)
 5         {
 6             daysArry = days;
 7         }
 8         public System.Collections.IEnumerator GetEnumerator()
 9         {
10             for (int i = 0; i < daysArry.Length; i++)
11             {
12                 yield return daysArry[i];
13             }
14         }
15     }
16 
17     class Program
18     {
19         static void Main(string[] args)
20         {
21             string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
22             var daysList = new DaysList<string>(days);
23 
24             foreach (string day in daysList)
25             {
26                 System.Console.WriteLine(day);
27             }
28             Console.ReadKey();
29         }
30     }

  通过查阅我们发现LIst是通过实现System.Collections.IEnumerable接口来达到可以被遍历的能力,而实现System.Collections.IEnumerable接口必须实现它里面的GetEnumerator()方法,用来返回一个循环访问集合的枚举器,代码段[2]中就有我对GetEnumerator()方法的实现,其中有个关键字[yield]不知大家注意到没。

  我的理解是:与其说是foreach遍历List,不如说是foreach遍历的是List中的GetEnumerator()方法返回的枚举器,注意这个枚举器实现了IEnumerator 接口,(插句话,IEnumerable接口标识某个类具备被遍历的能力,而IEnumerator 接口则使某个类真正具备这个能力!)。而当foreach对List进行循环遍历时,每个循环就是通过[yield]来分隔的。

三、对foreach的浅究

  通过标题二,我们大概对List进行了了解,但不清楚,下面看看foreach。

  依旧代码段[3]:

 1     //注意:其中类DaysList<T>的实现同代码段[2]一样
 2     //这里只展示foreach的实现。    
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
 8             var daysList = new DaysList<string>(days);
 9 
10             System.Collections.IEnumerator enumertor = daysList.GetEnumerator();
11             while (enumertor.MoveNext())
12             {
13                 System.Console.WriteLine(enumertor.Current);
14             }
15             Console.ReadLine();
16         }
17      }

  就像上面说的,foreach其实遍历的是List中的GetEnumerator()方法返回的枚举器enumertor,而这个枚举器所实现的接口IEnumerator中定义了只读的Current属性(用来获取枚举器当前的所指的集合中的元素)、MoveNext方法(将枚举器推进到集合中的下一个元素,返回值代表是否到了集合末尾)、Reset方法(使枚举器指到集合第一个元素之前,也就是重置枚举器),明白了这些,我们就可以像代码段[3]中一样通过[while]语法来实现跟foreach一样的功能了,而上文中的[yield]关键字浅显的理解就是用来划分要遍历的集合中的每个元素的。

  最后,本来还想分析分析这个实现了IEnumerator接口的枚举器是怎么生成的,想象一下它的内部实现,应该很有意思!

  就这样吧,下班了,大家共勉!

目录
相关文章
|
移动开发 Java Android开发
构建高效Android应用:Kotlin协程的实践之路
【2月更文挑战第31天】 在移动开发领域,性能优化和流畅的用户体验一直是开发者追求的目标。随着Kotlin语言的流行,其异步编程解决方案——协程(Coroutines),为Android应用带来了革命性的并发处理能力。本文将深入探讨Kotlin协程的核心概念、设计原理以及在Android应用中的实际应用案例,旨在帮助开发者掌握这一强大的工具,从而提升应用的性能和响应能力。
|
IDE 搜索推荐 编译器
使用esp8266使用小爱同学实现开灯与关灯操作
使用esp8266使用小爱同学实现开灯与关灯操作
450 0
|
SQL 存储 监控
功能解读|快速上手 OceanBase 数据迁移服务
在上一期的 OceanBase 功能解读系列文章中,我们为大家带来了 ODC 功能解读(戳这里回顾:《OceanBase 开发者中心 ODC 功能解读》),本文将为大家分享数据迁移服务的相关内容。
970 0
功能解读|快速上手 OceanBase 数据迁移服务
|
机器学习/深度学习
神经网络与深度学习---验证集(测试集)准确率高于训练集准确率的原因
神经网络与深度学习---验证集(测试集)准确率高于训练集准确率的原因
4353 2
|
机器学习/深度学习 数据采集 人工智能
函数式编程的实际应用
【10月更文挑战第12天】 函数式编程作为一种编程范式,在数据处理、金融、科学计算、Web 开发、游戏开发、物联网、人工智能等多个领域有着广泛应用。本文通过具体案例,详细介绍了函数式编程在这些领域的实际应用,展示了其在提高效率、确保准确性、增强可维护性等方面的显著优势。
722 60
|
11月前
|
人工智能 编解码 算法
MVPaint:腾讯PCG联合多所高校共同推出的3D纹理生成框架
MVPaint是由腾讯PCG联合多所高校共同推出的3D纹理生成框架,基于同步多视角扩散技术,实现高分辨率、无缝且多视图一致的3D纹理生成。该框架包含三个核心模块:同步多视角生成、空间感知3D修补和UV细化,显著提升3D模型的纹理生成效果。
211 2
MVPaint:腾讯PCG联合多所高校共同推出的3D纹理生成框架
|
11月前
|
自然语言处理 物联网 图形学
.NET 技术凭借其独特的优势和特性,为开发者们提供了一种高效、可靠且富有创造力的开发体验
本文深入探讨了.NET技术的独特优势及其在多个领域的应用,包括企业级应用、Web应用、桌面应用、移动应用和游戏开发。通过强大的工具集、高效的代码管理、跨平台支持及稳定的性能,.NET为开发者提供了高效、可靠的开发体验,并面对技术更新和竞争压力,不断创新发展。
432 7
|
11月前
|
监控 Linux 开发者
如何在 Linux 中优雅的使用 head 命令,用来看日志简直溜的不行
`head` 命令是 Linux 系统中一个非常实用的工具,用于快速查看文件的开头部分内容。本文介绍了 `head` 命令的基本用法、高级用法、实际应用案例及注意事项,帮助用户高效处理文件和日志,提升工作效率。
235 7
|
测试技术 开发工具 芯片
Open Chip Community (OCC)
Open Chip Community (OCC) 是一个开源芯片社区,旨在推动开源芯片的发展和普及。OCC 的目标是为开发人员提供一个开放透明的平台,让他们可以共同协作、创新和分享开源芯片技术。
979 3
|
人工智能 安全 数据安全/隐私保护
团队协作工具Slack介绍
团队协作工具Slack介绍
997 0