你真的了解foreach吗?
引言
有C#基础的,当问到循环有哪些,会毫不犹豫的说出的for、do while、foreach及while这几种,但是到具体实际开发中,我们遇到一些问题,比如:到底选择哪种?为什么选择这种?哪种好像都可以?,其实在大多数情况下基本上可以通用,但是遇到比如Dictionary <[key] , [value] >只能用foreach遍历,本文带你了解foreach的原理,以及使用场景。
foreach原理
在上边博客《IEnumerable和IEnumerator详解》中,我们自定义了一个集合People,在遍历的时候采用两种方法如下:
Person[] peopleArray = new Person[]
{
new Person("张三", ),
new Person("李四", ),
new Person("王五", ),
};
People peopleList = new People(peopleArray); //第一种方法(foreach)
foreach (Person p in peopleList)
{
Console.WriteLine(p.Name + "\t" + p.Age);
} //第二种方法(while)
IEnumerator enumeratorSimple = peopleList.GetEnumerator();
while (enumeratorSimple.MoveNext())
{
Person p = enumeratorSimple.Current as Person;
Console.WriteLine(p?.Name + "\t" + p?.Age);
}
上边的例子,两种遍历方式是等价,但是我们是否发现foreach遍历更加简洁,其实foreach相当于是一种语法糖,目的是让开发者写代码更加便捷。
官方给出的介绍如下:
foreach语句为类型实例中实现 System.Collections.IEnumerable 或 System.Collections.Generic.IEnumerable<T> 接口的每个元素执行语句或语句块。 foreach语句不局限于这些类型,它可应用于满足以下条件的任何类型的实例:
- 具有公共无参数GetEnumerator方法,其返回类型为类、结构或接口类型。
- GetEnumerator方法的返回类型具有公共Current属性和公共无参数MoveNext方法(其返回类型为 Boolean)。
大致意思只要继承IEnumerable 或.IEnumerable<T> 接口的类,都可以用foreach进行遍历,凡是用for可以遍历的数组,基本上都可以用foreach遍历。
foreach具体用法
遍历数组中的值,这种很简单,代码如下:
List<int> countList = new List<int>() {, , , , , };
foreach (var item in countList)
{
Console.WriteLine(item);
}
倘若我们遍历数据,并修改每项的值,这个怎么做,比如下边的代码:

当我们试图给item变量赋值的时候,vs智能提示,因为是迭代变量,无法赋值,也就是说当前变量是只读的,不能赋值,那基于这种情况,我们怎么整呢?
其实,foreach已经为我们提供了解决此问题的方法:用ref 迭代变量来设置 stackalloc 数组中每个项的值,具体代码如下:
Span<int> countList = stackalloc int[] { , , , , , };
foreach (ref int item in countList)
{
item++;
}
注意:“引用 foreach 迭代变量”只能在C#7.3及更高的版本中使用(其中,通过NuGet安装System.Memory),所以低版本开发的童鞋还是采用for遍历赋值吧,C#版本和.NET版本对应关系如下:
| C#版本 | .NET版本 | 发布日期 | 特性 |
|---|---|---|---|
| C# 1.0 | .NET Framework 1.0 | 2002-02-13 | 委托、事件 |
| C# 1.1 | .NET Framework 1.1 | 2003-04-24 | APM(异步编程模型) |
| C# 2.0 | .NET Framework 2.0 | 2005-11-07 | 泛型、匿名方法、迭代器、可空类型 |
| C# 3.0 | .NET Framework 3.0 | 2007-11-06 | 隐式类型 |
| .NET Framework 3.5 | 2007-11-19 | 对象集合初始化、自动实现属性、匿名类型、扩展方法、查询表达式、Lambda表达式、 表达式树、分部类和方法、Linq | |
| C# 4.0 | .NET Framework 4.0 | 2010-04-12 | 动态绑定、命名和可选参数、泛型的协变和逆变、互操作性 |
| C# 5.0 | .NET Framework 4.5 | 2012-08-15 | 异步和等待(async和await)、调用方信息(Caller Information) |
| C# 6.0 | .NET Framework 4.6 | 2015-07-20 | C# 6 中的新增功能 |
| .NET Core 1.0 | 2016-06-27 | ||
| C# 7.0 | .NET Framework 4.6.2 | 2016-08-02 | C# 7.0 中的新增功能 |
| C# 7.1 | .NET Framework 4.7 | 2017-04-05 | |
| .NET Core 2.0 | 2016-08-14 | .NET Core 2.0 的新增功能 | |
| C# 7.2 | .NET Framework 4.7.1 | 2017-10-17 | |
| C# 7.3 | .NET Framework 4.7.2 | 2018-04-30 | |
| .NET Core 2.1 | 2018-05-30 | .NET Core 2.1 的新增功能 | |
| .NET Core 2.2 | 2018-12-04 | .NET Core 2.2 的新增功能 | |
| C# 8.0 | .NET Framework 4.8 | 2019-04-18 | C# 8.0 中的新增功能 |
| .NET Core 3.0 | 2019-09-23 | .NET Core 3.0 的新增功能 |
总结
在开发过程,我们对某一知识点不仅要知道怎么用,而且还得知道为什么这么用,只有不断地总结,才能发现具体原理方法,只有这样才能真正的提升自己,不能为了敲代码而敲代码。文中若有不足之处,还望海涵,博文写作不易希望多多支持,后续会更新更多内容,感兴趣的朋友可以加关注,欢迎留言交流!
你真的了解foreach吗?的更多相关文章
- Unity减少GC Alloc之 使用for替换foreach
Unity中foreach会增加GC unity中for效率比foreach高? 在unity中使用foreach遍历集合会增加gc alloc,参考的话题:作为Unity3D的脚本而言,c#中for ...
- 【转】先说IEnumerable,我们每天用的foreach你真的懂它吗?
[转]先说IEnumerable,我们每天用的foreach你真的懂它吗? 我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq ...
- 先说IEnumerable,我们每天用的foreach你真的懂它吗?
我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq to Object中要返回IEnumerable? 接下来,先开始我们的正 ...
- foreach真的比for性能高吗
void Main() { ; List<int> list=new List<int>(); ;i<count;i++) { list.Add(i); } List&l ...
- C# 先说IEnumerable,我们每天用的foreach你真的懂它吗?
原文: http://www.cnblogs.com/zhaopei/p/5769782.html
- Foreach遍历
前天在项目中遇到一个问题,foreach遍历过程中修改responses中的对象,其中responses的类型:IEnumerable<Order>,代码如下: foreach (Orde ...
- 瞧一瞧,看一看呐,用MVC+EF快速弄出一个CRUD,一行代码都不用写,真的一行代码都不用写!!!!
瞧一瞧,看一看呐用MVC+EF快速弄出一个CRUD,一行代码都不用写,真的一行代码都不用写!!!! 现在要写的呢就是,用MVC和EF弄出一个CRUD四个页面和一个列表页面的一个快速DEMO,当然是在不 ...
- PHP中foreach循环详解
首先要说的是,其实我对foreach循环的用法并不是很精通,说详解,其实也只是我自己的理解,希望对你能有点帮助 . 先来看一下foreach的语法: foreach ($array as $key=& ...
- 【转】was mutated while being enumerated 你是不是以为你真的懂For...in... ??
原文网址:http://www.jianshu.com/p/ad80d9443a92 支持原创,如需转载, 请注明出处你是不是以为你真的懂For...in... ??哈哈哈哈, 我也碰到了这个报错 . ...
随机推荐
- Flask:Flask的模板系统和静态文件
1.Flask模板系统 Django框架有自己独立的模板系统,而Flask是没有的,Flask默认采用jinjia2模板系统,jinjia2是仿写Django模板系统的一个第三方模块,但性能上要比Dj ...
- 就因为加了Lombok的@Accessors(chain = true),bean拷贝工具类不干活了
前言 这次新建了一个工程,因为 Lombok 用得很习惯,但以前的话,一般只用了@Data,@AllArgsConstructor,@EqualsAndHashCode等常规注解:那这个Accesso ...
- Spring Boot (日志篇):Log4j2整合ELK,搭建实时日志平台
一.安装JDK1.8以上版本 1.从Oracle官网上下载Linux x64版本的 下载地址: http://www.oracle.com/technetwork/java/javase/downlo ...
- 27 个问题突破所有重难点,BroadcastReceiver 、ContentProvider 知多少?「建议收藏」
前言 距离上次更新过去一周多了,打破了之前两到三天一更的惯例,主要还是这部分内容太多了. 原先想把 BroadcastReceiver .ContentProvider 分两篇来总结,但的确,这两大组 ...
- Kruskal算法求最小生成树 笔记与思路整理
整理一下前一段时间的最小生成树的算法.(其实是刚弄明白 Kruskal其实算是一种贪心算法.先将边按权值排序,每次选一条没选过的权值最小边加入树,若加入后成环就跳过. 先贴张图做个示例. (可视化均来 ...
- 一个自动管理项目的Makefile(C语言)
Linux 是所有嵌入式软件工程师绕不过去的坎, makefile 是在Linux系统中绕不过去的坎. 花了几天时间初步学习和了解了makefile 的作用以及功能,并且制作了一个通用型的makefi ...
- 第六篇 视觉slam中的优化问题梳理及雅克比推导
优化问题定义以及求解 通用定义 解决问题的开始一定是定义清楚问题.这里引用g2o的定义. \[ \begin{aligned} \mathbf{F}(\mathbf{x})&=\sum_{k\ ...
- CF600E Lomsat gelral——线段树合并/dsu on tree
题目描述 一棵树有$n$个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 这个题意是真的窒息...具体意思是说,每个节点有一个颜色,你要找的是每个子树中颜色的众数 ...
- Android常见内存泄露
前言 对于内存泄漏,我想大家在开发中肯定都遇到过,只不过内存泄漏对我们来说并不是可见的,因为它是在堆中活动,而要想检测程序中是否有内存泄漏的产生,通常我们可以借助LeakCanary.MAT等工具来检 ...
- 误删tree命令如何恢复
误删tree命令如何恢复 考察rpm,yum的用法 一.删除tree命令,tree命令不可用 [root@centos7 ~]# which tree /usr/bin/tree [root@cent ...