引言

有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吗?的更多相关文章

  1. Unity减少GC Alloc之 使用for替换foreach

    Unity中foreach会增加GC unity中for效率比foreach高? 在unity中使用foreach遍历集合会增加gc alloc,参考的话题:作为Unity3D的脚本而言,c#中for ...

  2. 【转】先说IEnumerable,我们每天用的foreach你真的懂它吗?

    [转]先说IEnumerable,我们每天用的foreach你真的懂它吗? 我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq ...

  3. 先说IEnumerable,我们每天用的foreach你真的懂它吗?

    我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq to Object中要返回IEnumerable? 接下来,先开始我们的正 ...

  4. foreach真的比for性能高吗

    void Main() { ; List<int> list=new List<int>(); ;i<count;i++) { list.Add(i); } List&l ...

  5. C# 先说IEnumerable,我们每天用的foreach你真的懂它吗?

    原文: http://www.cnblogs.com/zhaopei/p/5769782.html

  6. Foreach遍历

    前天在项目中遇到一个问题,foreach遍历过程中修改responses中的对象,其中responses的类型:IEnumerable<Order>,代码如下: foreach (Orde ...

  7. 瞧一瞧,看一看呐,用MVC+EF快速弄出一个CRUD,一行代码都不用写,真的一行代码都不用写!!!!

    瞧一瞧,看一看呐用MVC+EF快速弄出一个CRUD,一行代码都不用写,真的一行代码都不用写!!!! 现在要写的呢就是,用MVC和EF弄出一个CRUD四个页面和一个列表页面的一个快速DEMO,当然是在不 ...

  8. PHP中foreach循环详解

    首先要说的是,其实我对foreach循环的用法并不是很精通,说详解,其实也只是我自己的理解,希望对你能有点帮助 . 先来看一下foreach的语法: foreach ($array as $key=& ...

  9. 【转】was mutated while being enumerated 你是不是以为你真的懂For...in... ??

    原文网址:http://www.jianshu.com/p/ad80d9443a92 支持原创,如需转载, 请注明出处你是不是以为你真的懂For...in... ??哈哈哈哈, 我也碰到了这个报错 . ...

随机推荐

  1. win系统下之docker安装centos7镜像

    1)    拉取镜像 输入命令docker pull centos:7 从仓库拉取centos7的镜像 2)    查看本地镜像 命令:docker images 可以查看已经把centos的镜像拉取 ...

  2. 自建windows服务器如何部署egg应用

    1. 使用IE浏览器登陆VPN 2. 远程登陆 3. 在服务器安装最新的node.js,git等 4. 下载源码 > git clone ****.git 5. npm安装依赖 > cd ...

  3. 使用ASP.NET Core 3.x 构建 RESTful API - 1.准备工作

    以前写过ASP.NET Core 2.x的REST API文章,今年再更新一下到3.0版本. 先决条件 我在B站有一个非常入门的ASP.NET Core 3.0的视频教程,如果您对ASP.NET Co ...

  4. mysql设计规范一

    原文地址:http://www.jianshu.com/p/33b7b6e0a396 主键 表中每一行都应该有可以唯一标识自己的一列(或一组列). 一个顾客可以使用顾客编号列,而订单可以使用订单ID, ...

  5. Angular开发规范

    目录  一.         前言 1.1.       规范目的 1.2.       局限性 二.         文件规范 2.1.       文件结构约定 2.2.       单一职责原则 ...

  6. [考试反思]1103csp-s模拟测试99: 美梦

    可能这次考得好的原因就是熬夜颓废到不算太晚?(啪) 但是是真心困. 考前跟akt说:我希望今天考一点那种不用动脑子,就是一直码的题. 然后开门T1一道线段树维护单调栈的板子我就...了 当时调了一上午 ...

  7. [考试反思]0920csp-s模拟测试48:弱小

    注:T1全场46个人里42个AC了. %%%zkt也AK了呢越来越强啊 我是真的越来越弱了吗? 我到底在干什么... 在难度递增的题里分数递增... 考试过程大体还好,但是如此快速地WA掉T1也真是蠢 ...

  8. 大厂面试经:说一下你们线上JVM是如何优化的?

    JVM(Java虚拟机)简单来说就是运行Java代码的解释器,作为螺丝钉程序员JVM其实了解下就差不多啦,不懂JVM内部细节照样能写出优质的代码!但是一到造火箭.飞机的场景(面试)不懂JVM的你,会被 ...

  9. Html5在网页中引入视频音频的方法

    1.<video> 标签定义视频,比如电影片段或其他视频流. 一段简单的 HTML5 视频: <video src="movie.ogg" controls=&q ...

  10. 关闭redis持久化功能

    关闭redis持久化功能持久化会报如下信息 会影响硬盘写入性能 所以没什么用 就关掉吧 修改redis配置文件,redis.conf 第115行左右. 1.注释掉原来的持久化规则 <pre> ...