引用 foreach 迭代变量”在C#7.3

引言

有C#基础的,当问到循环有哪些,会毫不犹豫的说出的for、do while、foreach及while这几种,但是到具体实际开发中,我们遇到一些问题,比如:到底选择哪种?为什么选择这种?哪种好像都可以?,其实在大多数情况下基本上可以通用,但是遇到比如Dictionary <[key] , [value] >只能用foreach遍历,本文带你了解foreach的原理,以及使用场景。

foreach原理

在上边博客《IEnumerable和IEnumerator详解》中,我们自定义了一个集合People,在遍历的时候采用两种方法如下:

Person[] peopleArray = new Person[3]
{
      new Person("张三", 15),
      new Person("李四", 18),
      new Person("王五", 21),
};
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>() {0, 1, 2, 3, 4, 5};
foreach (var item in countList)
{
      Console.WriteLine(item);
}

倘若我们遍历数据,并修改每项的值,这个怎么做,比如下边的代码:

当我们试图给item变量赋值的时候,vs智能提示,因为是迭代变量,无法赋值,也就是说当前变量是只读的,不能赋值,那基于这种情况,我们怎么整呢?

其实,foreach已经为我们提供了解决此问题的方法:用ref 迭代变量来设置 stackalloc 数组中每个项的值,具体代码如下:

Span<int> countList = stackalloc int[] { 0, 1, 2, 3, 4, 5 };
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 的新增功能

总结

在开发过程,我们对某一知识点不仅要知道怎么用,而且还得知道为什么这么用,只有不断地总结,才能发现具体原理方法,只有这样才能真正的提升自己,不能为了敲代码而敲代码。文中若有不足之处,还望海涵,博文写作不易希望多多支持,后续会更新更多内容,感兴趣的朋友可以加关注,欢迎留言交流!

原文地址:https://www.cnblogs.com/Leo_wl/p/12315417.html

时间: 2024-10-07 17:11:12

引用 foreach 迭代变量”在C#7.3的相关文章

探究foreach对于迭代变量的封装性的研究

众所周知教科书上对于foreach之中的注释是在遍历过程中无法改变其遍历的元素例如声明一个数组 int[] ii={0,1,2,3}; foreach(int m in ii){ m = 3;//错误 “m”是一个“foreach 迭代变量”,无法为它赋值 Console.WriteLine(m); } 由上面可以知道,我们无法改变数组里面的值,但是foreach语句是为了集合而创建的,数组只是集合的一种,而其他集合会是怎么样的呢?C#里面为我们创建好了好几个集合类,List<T> ,Arra

C# foreach 值类型及引用类型迭代变量改变的方式

C#中foreach不能改变迭代变量的值 然而此种说法只适用与值类型,更改值类型时会改变在栈上的内存分布 引用类型由于是引用地址的变更,不影响内存分布,所以能够在foreach中更改 至于引用类型中的特殊string类型,猜想是因为string类型的变更不是地址的更改,而是会在堆上面重新开辟一块,所以应该也是会影戏到内存分布 原文地址:https://www.cnblogs.com/X-Q-X/p/10402479.html

编程题:引用共用体变量的成员

编程题:引用共用体变量的成员 #include<stdio.h> void main() {  union temp {char a; int b; }t; t.a=66;t.b=266; /*266=256+10即266的二进制为100001010,所以高字节放低字节放10*/ printf("%x:%d,%x:%d\n",&t.a,t.a,&t.b,t.b); } 分析代码的算法: 运行结果: 编程题:引用共用体变量的成员,布布扣,bubuko.com

ERROR无法从静态上下文中引用非静态变量

ERROR无法从静态上下文中引用非静态变量 2012-06-16 20:58:52 分类: Java 什么是“static”? 学习过java.C++或C的人都应该认识这个关键字.用这个关键字修饰的变量叫做静态变量,有其特殊的作用.在java中static也用来修饰静态方法和静态内部类. 静态变量的特点: (1)生存周期:静态局部变量的生存周期也是整个源程序.当定义整个变量的函数结束时,整个变量并没有消失,他始终是存在的. (2)作用域:作用域与自动变量是一样的,只能在定义其的子函数中使用,当退

【转】python共享引用(多个变量引用)示例代码

python共享引用(多个变量引用)示例代码_python_脚本之家http://www.jb51.net/article/44109.htm python单个(一个)对象被多个变量引用又是怎么一回事儿呢?看下面代码 a = 3b = a 先上图(图1)吧,大家一看就一目了然了: 变量名和对象,在运行赋值语句b = a之后,变量a,b都指向了对象3的内存空间. 假设这时执行 a = 'python', a将指向刚创建的字符串对象. 我们再来试试这种情况: >>>list_1 = [1,2

一个注意事项:内部类引用的外部变量必须是final的

之前写过一个项目,好久没更新了,最近翻起以前的代码,发现在这里报了一个错.(现在转到Intellij了,从前在Eclipse luna中是可以编译通过的,Eclipse mars也会报错,JDK版本都是1.8,还没去查为什么) 为什么在内部类中引用外部变量时,必须声明为final呢? 最开始我想的是,会和Java的内存模型有关.因为我们都知道,带有static的变量或者方法是属于类的,也就是说,类成员是被储存在堆内存里面的.那么final是否也是这样?经过查找资料,得知:final 是保护 所修

报错!无法从静态上下文中引用非静态 变量

1 import java.awt.Point; 2 class rectangle 3 { int x1=0; 4 int y1=0; 5 int x2=0; 6 int y2=0; 7 8 rectangle point(int x,int y,int z,int w) 9 {x1= x; 10 y1= y; 11 x2= z; 12 y2= w; 13 return this; 14 } 15 16 public static void main(String[] args) 17 18

内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例

内部类访问外部类的变量必须是final吗? 如下:class A{int i = 3;public void shout(){ class B{public void shout1(){System.out.println(i);} }B b=new B();b.shout1();} public static void main(String [] args){A a=new A();a.shout();} }可正常输出3,证明可以访问类的变量i,但改为下面的方式:class A{public

C#拾遗之foreach迭代语句

C#语言提供了一个for语句循环的捷径,而且还促进了集合类的更为一致,它就是foreach语句. foreach语句的定义格式为: foreach(类型   变量  in   集合) { 子语句: } 每执行一次内嵌语句,循环变量就依次取集合中的一个元素代入其中,在这里,循环变量是一个只读型局部变量,如试图改变其值将会发生编译错误. foreach语句用于列举出集合中所有的元素,foreach语句中的表达式由关键字in隔开的两个项组成.in右边的项是集合名,in左边的项是变量名,用来存放该集合中