zoukankan      html  css  js  c++  java
  • C#学习之foreach循环原理

     

    C#学习之foreach循环原理

    结构篇:

    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为止,此时循环停止。

     

    [csharp] view plaincopy
    1. //替代foreach实现:  
    2. foreach (XXX a in b){   
    3. ...   
    4. }   
    5.   
    6. //等同于  
    7. XXX a;  
    8. IEnumerator ie = (IEnumable)b.GetEnumerator();   
    9. while (ie.MoveNext) {   
    10. a = (XXX)ie.Current;   
    11. ...  
    12. }  

     

    具体示例:

     

    [csharp] view plaincopy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5. using System.Collections;  
    6.   
    7. namespace _07foreach循环遍历原理  
    8. {  
    9.     class Program  
    10.     {  
    11.         //foreach循环中的Var关键字  
    12.         //var是一个”类型推断“,在程序编译的时候就已经替换成了对应的数据类型。  
    13.         //所以说var是一个强类型(在编译的时候已经可以确定数据类型了。),而不是弱类型。  
    14.         static void Main(string[] args)  
    15.         {  
    16.             #region 示例练习  
    17.             Console.WriteLine("=============1===========");  
    18.             ArrayList list1 = new ArrayList() { 20, 3, 49, 39, 48 };  
    19.             foreach (var item in list1)  
    20.             {  
    21.                 Console.WriteLine(item);  
    22.             }  
    23.   
    24.             Console.WriteLine("=============2===========");  
    25.             string[] names = { "a""b""c""d" };  
    26.             foreach (var item in names)//var可以用 string代替  
    27.             {  
    28.                 Console.WriteLine(item);  
    29.             }  
    30.   
    31.             Console.WriteLine("=============3===========");  
    32.             List<string> list2 = new List<string>() { "乔丹""可比""詹姆斯" };  
    33.             foreach (var item in list2)//var可以用 string代替  
    34.             {  
    35.                 Console.WriteLine(item);  
    36.             }  
    37.             #endregion  
    38.  
    39.             #region foreach原理初探  
    40.             //任何类型,只要想使用foreach来循环遍历,就必须在当前类型中存在:  
    41.             //public IEnumerator GetEnumerator()方法,(一般情况我们会通过实现IEnumerable接口,来创建该方法。)  
    42.             Console.WriteLine("=============4===========");  
    43.             Person p = new Person();  
    44.             p[0] = "BMW";  
    45.             p[1] = "凯迪拉克";  
    46.             p[2] = "阿斯顿马丁";  
    47.             //for循环遍历输出  
    48.             Console.WriteLine("=======for循环遍历输出======");  
    49.             for (int i = 0; i < p.Count; i++)  
    50.             {  
    51.                 Console.WriteLine(p[i]);  
    52.             }  
    53.             //foreach循环遍历输出  
    54.             Console.WriteLine("=======foreach循环遍历输出======");  
    55.             foreach (var item in p)  
    56.             {  
    57.                 Console.WriteLine(item);  
    58.             }  
    59.             //foreach循环原理遍历输出  
    60.             Console.WriteLine("=======foreach循环原理遍历输出======");  
    61.             IEnumerator etor = p.GetEnumerator();  
    62.             while (etor.MoveNext())  
    63.             {  
    64.                 string str = etor.Current.ToString();  
    65.                 Console.WriteLine(str);  
    66.             }  
    67.             #endregion  
    68.   
    69.             Console.ReadKey();  
    70.         }  
    71.     }  
    72.   
    73.     public class Person :IEnumerable  
    74.     {  
    75.         private List<string> listCar = new List<string>();  
    76.   
    77.         public int Count   
    78.         {  
    79.             get   
    80.             {  
    81.                 return this.listCar.Count;  
    82.             }  
    83.         }  
    84.   
    85.         public string this[int index]  
    86.         {  
    87.             get  
    88.             {  
    89.                 return listCar[index];  
    90.             }  
    91.             set   
    92.             {  
    93.                 if (index >= listCar.Count)  
    94.                 {  
    95.                     listCar.Add(value);  
    96.                 }  
    97.                 else   
    98.                 {  
    99.                     listCar[index] = value;  
    100.                 }  
    101.             }  
    102.         }  
    103.   
    104.         public string Name  
    105.         {  
    106.             get;  
    107.             set;  
    108.         }  
    109.   
    110.         public int Age  
    111.         {  
    112.             get;  
    113.             set;  
    114.         }  
    115.   
    116.         public string Email  
    117.         {  
    118.             get;  
    119.             set;  
    120.         }  
    121.   
    122.         //这个方法的作用不是用来遍历的,而是用来获取 一个对象  
    123.         //这个对象才是用来遍历的  
    124.         public IEnumerator GetEnumerator()  
    125.         {  
    126.             return new PersonEnumerator(listCar);  
    127.         }  
    128.     }  
    129.   
    130.     /// <summary>  
    131.     /// 这个类型的作用就是 用来遍历Person中的List集合的  
    132.     /// </summary>  
    133.     public class PersonEnumerator : IEnumerator  
    134.     {  
    135.         public PersonEnumerator(List<string> _cars)  
    136.         {  
    137.             this.cars = _cars;  
    138.         }  
    139.   
    140.         //这个字段中存储的就是Person对象中的listCar集合  
    141.         private List<string> cars;  
    142.   
    143.         //假设一开始遍历的对象的索引是-1  
    144.         private int index = -1;  
    145.   
    146.         //表示获取当前正在遍历的那个对象  
    147.         public object Current  
    148.         {  
    149.             get   
    150.             {  
    151.                 if (index<0)  
    152.                 {  
    153.                     return null;  
    154.                 }  
    155.                 return cars[index];  
    156.             }  
    157.         }  
    158.   
    159.         //让自定义下标index累加  
    160.         public bool MoveNext()  
    161.         {  
    162.             index = index + 1;  
    163.             if (index>=cars.Count)  
    164.             {  
    165.                 return false;  
    166.             }  
    167.             else  
    168.             {  
    169.                 return true;  
    170.             }  
    171.         }  
    172.   
    173.         //重置  
    174.         public void Reset()  
    175.         {  
    176. ASP.Net+Android+IOS开发.Net培训、期待与您交流! important; padding-right: 3px !important; border-top-style: none; color: #5c5c5c; padding-top: 0px !important;">            index = -1;  
    177.         }  
    178.     }  
    179. }  

    输出结果如下:

    可以根据下图进行深入理解foreach执行原理:

     

  • 相关阅读:
    信号量Semaphore的使用
    Future和FutureTask
    阻塞队列和线程池
    Java多线程基础
    Java常用方法
    Scanner和BufferedReader的区别和用法
    QT学习笔记9:QTableWidget的用法总结
    WordPress 建站教程:新手搭建 WordPress个人博客图文教程(完全版)
    Let's do it
    jdk alternatives
  • 原文地址:https://www.cnblogs.com/chenanzixue/p/3445833.html
Copyright © 2011-2022 走看看