foreach 语句为数组或对象集合中的每个元素重复一个嵌入语句组。foreach 语句用于循环访问集合以获取所需信息,但不应用于更改集合内容以避免产生不可预知的副作用。此语句的形式如下:
foreach (type identifier in expression) statement
其中:
type
identifier 的类型。
identifier
表示集合元素的迭代变量。如果迭代变量为值类型,则无法修改的只读变量也是有效的。
expression
对象集合或数组表达式。集合元素的类型必须可以转换为 identifier 类型。请不要使用计算为 null 的表达式。
而应计算为实现 IEnumerable 的类型或声明 GetEnumerator 方法的类型。在后一种情况中,GetEnumerator 应该要么返回实现 IEnumerator 的类型,要么声明 IEnumerator 中定义的所有方法。
statement
要执行的嵌入语句。
原理篇:
在foreach循环中,迭代集合collectionObject的过程如下:
(1)调用collectionObject.GetEnumerator(),返回一个IEnumerator引用。这个方法可以通过IEnumerable接口的实现代码来获得。但这是可选的。
(2)调用返回的IEnumerator接口的MoveNext()方法。
(3)如果MoveNext()方法返回true,就使用IEnumerator接口的Current属性获取对象的一个引用,用于foreach循环。
(4)重复前面两步,直到MoveNext()方法返回false为止,此时循环停止。
- //替代foreach实现:
- foreach (XXX a in b){
- ...
- }
- //等同于
- XXX a;
- IEnumerator ie = (IEnumable)b.GetEnumerator();
- while (ie.MoveNext) {
- a = (XXX)ie.Current;
- ...
- }
具体示例:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
- namespace _07foreach循环遍历原理
- {
- class Program
- {
- //foreach循环中的Var关键字
- //var是一个”类型推断“,在程序编译的时候就已经替换成了对应的数据类型。
- //所以说var是一个强类型(在编译的时候已经可以确定数据类型了。),而不是弱类型。
- static void Main(string[] args)
- {
- #region 示例练习
- Console.WriteLine("=============1===========");
- ArrayList list1 = new ArrayList() { 20, 3, 49, 39, 48 };
- foreach (var item in list1)
- {
- Console.WriteLine(item);
- }
- Console.WriteLine("=============2===========");
- string[] names = { "a", "b", "c", "d" };
- foreach (var item in names)//var可以用 string代替
- {
- Console.WriteLine(item);
- }
- Console.WriteLine("=============3===========");
- List<string> list2 = new List<string>() { "乔丹", "可比", "詹姆斯" };
- foreach (var item in list2)//var可以用 string代替
- {
- Console.WriteLine(item);
- }
- #endregion
- #region foreach原理初探
- //任何类型,只要想使用foreach来循环遍历,就必须在当前类型中存在:
- //public IEnumerator GetEnumerator()方法,(一般情况我们会通过实现IEnumerable接口,来创建该方法。)
- Console.WriteLine("=============4===========");
- Person p = new Person();
- p[0] = "BMW";
- p[1] = "凯迪拉克";
- p[2] = "阿斯顿马丁";
- //for循环遍历输出
- Console.WriteLine("=======for循环遍历输出======");
- for (int i = 0; i < p.Count; i++)
- {
- Console.WriteLine(p[i]);
- }
- //foreach循环遍历输出
- Console.WriteLine("=======foreach循环遍历输出======");
- foreach (var item in p)
- {
- Console.WriteLine(item);
- }
- //foreach循环原理遍历输出
- Console.WriteLine("=======foreach循环原理遍历输出======");
- IEnumerator etor = p.GetEnumerator();
- while (etor.MoveNext())
- {
- string str = etor.Current.ToString();
- Console.WriteLine(str);
- }
- #endregion
- Console.ReadKey();
- }
- }
- public class Person :IEnumerable
- {
- private List<string> listCar = new List<string>();
- public int Count
- {
- get
- {
- return this.listCar.Count;
- }
- }
- public string this[int index]
- {
- get
- {
- return listCar[index];
- }
- set
- {
- if (index >= listCar.Count)
- {
- listCar.Add(value);
- }
- else
- {
- listCar[index] = value;
- }
- }
- }
- public string Name
- {
- get;
- set;
- }
- public int Age
- {
- get;
- set;
- }
- public string Email
- {
- get;
- set;
- }
- //这个方法的作用不是用来遍历的,而是用来获取 一个对象
- //这个对象才是用来遍历的
- public IEnumerator GetEnumerator()
- {
- return new PersonEnumerator(listCar);
- }
- }
- /// <summary>
- /// 这个类型的作用就是 用来遍历Person中的List集合的
- /// </summary>
- public class PersonEnumerator : IEnumerator
- {
- public PersonEnumerator(List<string> _cars)
- {
- this.cars = _cars;
- }
- //这个字段中存储的就是Person对象中的listCar集合
- private List<string> cars;
- //假设一开始遍历的对象的索引是-1
- private int index = -1;
- //表示获取当前正在遍历的那个对象
- public object Current
- {
- get
- {
- if (index<0)
- {
- return null;
- }
- return cars[index];
- }
- }
- //让自定义下标index累加
- public bool MoveNext()
- {
- index = index + 1;
- if (index>=cars.Count)
- {
- return false;
- }
- else
- {
- return true;
- }
- }
- //重置
- public void Reset()
- {
- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! important; padding-right: 3px !important; border-top-style: none; color: #5c5c5c; padding-top: 0px !important;"> index = -1;
- }
- }
- }
输出结果如下:
可以根据下图进行深入理解foreach执行原理: