zoukankan      html  css  js  c++  java
  • foreach内部做的一点事

      1 在C#中,foreach的使用简化了很多循环语法的书写。如果我们仅仅把foreach当成for循环的省略写法的话,就显得有点大才小用了。
      2 
      3 事实上,foreach与“迭代”和“枚举”密切相关。
      4 
      5 C#编译器会把foreach语句转换为IEnumerable接口的方法和属性。
      6 
      7 例如:
      8 
      9  foreach (var p in persons)            
     10 
     11 {
     12 
     13 Console.WriteLine(p);     
     14 
     15 }
     16 
     17 以上代码迭代persons数组中的所有元素,并逐个显示他们。
     18 
     19 foreach语句会解析成下面的代码。首先调用GetEnumerator()方法,获得数组的一个枚举。
     20 
     21 在while循环中(只要MoveNext()返回true),用Current属性访问数组中的元素:
     22 
     23 IEnumerator enumerator = persons.GetEnumerator();            
     24 
     25 while (enumerator.MoveNext())            
     26 
     27 {                
     28 
     29 Person p = (Person) enumerator.Current; Console.WriteLine(p);            
     30 
     31 }
     32 
     33 这里要说明的是。用[]声明数组是C#中使用Array类的记号。Array类实现了IEnumerable接口中的GetEnumerator()方法。
     34 
     35 所以使用foreach语句迭代数组,其实是使用了Array类中个GetEnumerator()方法。
     36 
     37 也就是说,只要是实现了IEnumerable接口中的GetEnumerator()方法的类,都可以用foreach语句来迭代。
     38 
     39 IEnumerable接口中的GetEnumerator()方法是这样定义的:
     40 
     41 IEnumerator GetEnumerator()
     42 
     43 其返回的类型是一个IEnumerator接口。
     44 
     45 IEnumerator接口中的Current属性返回光标所在的元素。
     46 
     47 IEnumerator接口中的MoveNext()方法移动到集合的下一个元素上,如果有这个元素,该方法就返回true。如果集合不再有更多的元素,该方法就返回false。
     48 
     49 IEnumerator接口中的Reset()方法将光标重新定位于集合的开头。许多枚举会抛出NotSupportedException异常。
     50 
     51 下面,我们来写一个实现了IEnumerable接口的类。
     52 
     53  public class HelloCollection:IEnumerable                    
     54 
     55 {                        
     56 
     57     public IEnumerator GetEnumerator()                        
     58 
     59    {                            
     60 
     61      yield return "Hello";                            
     62 
     63      yield return "World";                        
     64 
     65    }                    
     66 
     67 }
     68 
     69 现在可以用foreach语句迭代了:
     70 
     71 static void Main(string[] args)        
     72 
     73 {
     74 
     75          HelloCollection helloCollection=new HelloCollection ();            
     76 
     77          foreach (string s in helloCollection )            
     78 
     79          {                
     80 
     81          Console.WriteLine(s);            
     82 
     83          }        
     84 
     85 }
     86 
     87 实际上,yield return语句返回集合的一个元素,并移动到下一个元素上。它会将类HelloCollection解析成如下代码:
     88 
     89  public class HelloCollection : IEnumerable        
     90 
     91 {            
     92 
     93     public IEnumerator GetEnumerator()            
     94 
     95    {                
     96 
     97       Enumertor enumerator = new Enumerator();                
     98 
     99       return enumerator;            
    100 
    101    }
    102 
    103    public class Enumertor : IEnumerator, IDisposable            
    104 
    105   {                
    106 
    107       private int state;                
    108 
    109       private object current;
    110 
    111       public Enumertor(int state)                
    112 
    113      {                    
    114 
    115         this.state = state;                
    116 
    117      }            
    118 
    119   }                
    120 
    121      bool System.Collections .IEnumerator .MoveNext()                
    122 
    123    {                    
    124 
    125      switch (state)                    
    126 
    127        {                        
    128 
    129           case 0:                            
    130 
    131           current = "Hello";                            
    132 
    133           state = 1;                            
    134 
    135           return true;                        
    136 
    137           case 1:                            
    138 
    139           current = "World";                           
    140 
    141          state = 2;                            
    142 
    143          return true ;                        
    144 
    145          case 2:                            
    146 
    147          break ;                    
    148 
    149       }                    
    150 
    151     return false ;                
    152 
    153     }
    154 
    155   void System.Collections .IEnumerator .Reset()                
    156 
    157    {                    
    158 
    159      throw new NotSupportedException();                
    160 
    161    }
    162 
    163   object System.Collections .IEnumerator .Current                
    164 
    165   {                    
    166 
    167       get 
    168 
    169          {
    170 
    171             return current;
    172 
    173          }                
    174 
    175     }                
    176 
    177 void IDisposable.Dispose()                
    178 
    179    {                
    180 
    181    }        
    182 
    183 }
    184 
    185  
    186 
    187  
    188 
    189  
    190 
    191 foreach语句默认用GetEnumerator()方法迭代,也可以自行制定迭代方法。举例:
    192 
    193 public class MusicTitles:IEnumerable        
    194 
    195 {            
    196 
    197    string[] names = { "Tubular Bells", "Hergest Ridge", "Ommadawn", "Platinum" };
    198 
    199    public IEnumerator GetEnumerator()  /*顺序迭代*/            
    200 
    201    {                
    202 
    203      for (int i = 0; i < 4; i++)                    
    204 
    205      yield return names[i];            
    206 
    207     }
    208 
    209    public IEnumerator Reverse()  /*逆序迭代*/            
    210 
    211     {                
    212 
    213        for (int i = 3; i >= 0; i--)                    
    214 
    215        yield return names[i];            
    216 
    217     }        
    218 
    219 }
    220 
    221 在foreach语句中不必写明使用GetEnumerator()方法迭代,因为这是默认方法。如下:
    222 
    223 static void Main(string[] args)        
    224 
    225 {
    226 
    227     MusicTitles titles = new MusicTitles();            
    228 
    229     foreach (string title in titles)            
    230 
    231     {                
    232 
    233       Console.WriteLine(title);            
    234 
    235      }
    236 
    237     Console.WriteLine();
    238 
    239     foreach (string title in titles.Reverse())            
    240 
    241     {                
    242 
    243      Console.WriteLine(title);            
    244 
    245     }        
    246 
    247 }
  • 相关阅读:
    推荐系统对外服务接口解决方案
    Windows Forms框架编程
    从Membership 到 .NET4.5 之 ASP.NET Identity
    Asp.net MVC的Model Binder工作流程以及扩展方法(1)
    C#异常处理经验(原则与方法)
    sed(转)
    为什么小草能从石头底下钻出来?你要是平平淡淡,也可能就被踩死了,没生命力了。反倒是重压之下想方设法找个空儿往外挤
    《Android底层接口与驱动开发技术详解》digest
    或许,大家知道小黄鸡是一个机器人之后,会很失望。但是,这似乎也说明了,能随叫随到陪你聊天的人,或许是不存在的
    java转换字符串的编码(转)
  • 原文地址:https://www.cnblogs.com/yellow-Li/p/3764158.html
Copyright © 2011-2022 走看看