1. <dd id="erndk"></dd>
                1. 迭代器模式隨想

                  micDavid 2019/9/4 21:26:52

                  一、什么是迭代器模式?定義:提供一種順序訪問集合的方法,而不暴露集合內部的表示順序訪問,y(挨個訪問),不暴露集合內部表示,反映了面向對象程序中的封裝性??梢赃@么理解,一組模特從后臺出場,一個接著一個,但是先出場的模特,未必是站在最前面的模特。換句話說,對于觀眾,你不知道后臺模

                  一、什么是迭代器模式?

                  定義:提供一種順序訪問集合的方法,而不暴露集合內部的表示

                  順序訪問,one by one(挨個訪問),不暴露集合內部表示,反映了面向對象程序中的封裝性??梢赃@么理解,一組模特從后臺出場,一個接著一個,但是先出場的模特,未必是站在最前面的模特。換句話說,對于觀眾,你不知道后臺模特的特定位置。為什么是順序訪問呢?因為迭代器模式采用的輸出機制是內部決定好的,你無法決定。不像字典類型,我傳不同的key,可以訪問不同的value。我們訪問列表,可以直接訪問第i個元素,但是迭代器,你想要訪問下一個元素,必須把當前的元素訪問過后,才能到下一個元素。

                  二、c#中的迭代器接口

                   

                   迭代器接口,可以手動實現調用,如下:

                   1     public class MyIEnumerator : IEnumerator<string>
                   2     {
                   3         string[] types = { "下等馬", "上等馬", "中等馬" };
                   4 
                   5         int cur = -1;
                   6         public string Current
                   7         {
                   8             get
                   9             {
                  10                 return types[cur];
                  11             }
                  12         }
                  13         object IEnumerator.Current
                  14         {
                  15             get
                  16             {
                  17                 return this.Current;
                  18             }
                  19         }
                  20 
                  21         public void Dispose()
                  22         {
                  23         }
                  24 
                  25         public bool MoveNext()
                  26         {
                  27             if (cur < types.Length - 1)
                  28             {
                  29                 cur++;
                  30                 return true;
                  31             }
                  32             return false;
                  33         }
                  34 
                  35         public void Reset()
                  36         {
                  37             cur = -1;
                  38         }
                  39     }

                  話說田忌賽馬,按一定的出場順序贏得了齊威王,此策略是由孫臏提出的,再看看調用:

                  1      MyIEnumerator m = new MyIEnumerator();
                  2      while (true)
                  3       {
                  4           if (m.MoveNext()) { Console.WriteLine(m.Current); }
                  5           else break;
                  6       }

                  顯然手動編寫代碼,比較麻煩,搞不好還弄個數組越界,我們看看c#中可枚舉接口:

                   

                   此接口只有一個實現迭代器的方法,我們知道凡是實現了這個接口的,都可以用foreach循環,我們把調用迭代器的方法改成foreach自動調用

                   1    public class MyEnumerable : IEnumerable<string>
                   2     {
                   3         public IEnumerator<string> GetEnumerator()
                   4         {
                   5             return new MyIEnumerator();
                   6         }
                   7 
                   8         IEnumerator IEnumerable.GetEnumerator()
                   9         {
                  10             return GetEnumerator();
                  11         }
                  12     }
                  1   MyEnumerable a = new MyEnumerable();
                  2    foreach (var item in a)
                  3    {
                  4        Console.WriteLine(item);
                  5    }

                  可能有人問了,你改成foreach循環和手動循環調用有什么區別?可以這么說吧,foreach進一步簡化了調用,你不用控制循環什么時候結束,你也不要操心怎么訪問下一個元素。

                  可見迭代器的調用已經很優雅了,如果迭代器的創建能夠簡化,那么就更好了,c#中提供了yield關鍵字。

                  1         public IEnumerator<string> GetEnumerator()
                  2         {
                  3             yield return "下等馬";
                  4             yield return "上等馬";
                  5             yield return "中等馬";
                  6         }

                  通過6行代碼,編譯器就為我們創建好了迭代器,如下所示:

                   1 public class MyEnumerable : IEnumerable<string>, IEnumerable
                   2 {
                   3     // Methods
                   4     [IteratorStateMachine(typeof(<GetEnumerator>d__0))]
                   5     public IEnumerator<string> GetEnumerator()
                   6     {
                   7         yield return "下等馬";
                   8         yield return "上等馬";
                   9         yield return "中等馬";
                  10     }
                  11 
                  12     IEnumerator IEnumerable.GetEnumerator()
                  13     {
                  14         return this.GetEnumerator();
                  15     }
                  16 
                  17     // Nested Types
                  18     [CompilerGenerated]
                  19     private sealed class <GetEnumerator>d__0 : IEnumerator<string>, IDisposable, IEnumerator
                  20     {
                  21         // Fields
                  22         private int <>1__state;
                  23         private string <>2__current;
                  24         public MyEnumerable <>4__this;
                  25 
                  26         // Methods
                  27         [DebuggerHidden]
                  28         public <GetEnumerator>d__0(int <>1__state)
                  29         {
                  30             this.<>1__state = <>1__state;
                  31         }
                  32 
                  33         private bool MoveNext()
                  34         {
                  35             switch (this.<>1__state)
                  36             {
                  37                 case 0:
                  38                     this.<>1__state = -1;
                  39                     this.<>2__current = "下等馬";
                  40                     this.<>1__state = 1;
                  41                     return true;
                  42 
                  43                 case 1:
                  44                     this.<>1__state = -1;
                  45                     this.<>2__current = "上等馬";
                  46                     this.<>1__state = 2;
                  47                     return true;
                  48 
                  49                 case 2:
                  50                     this.<>1__state = -1;
                  51                     this.<>2__current = "中等馬";
                  52                     this.<>1__state = 3;
                  53                     return true;
                  54 
                  55                 case 3:
                  56                     this.<>1__state = -1;
                  57                     return false;
                  58             }
                  59             return false;
                  60         }
                  61 
                  62         [DebuggerHidden]
                  63         void IEnumerator.Reset()
                  64         {
                  65             throw new NotSupportedException();
                  66         }
                  67 
                  68         [DebuggerHidden]
                  69         void IDisposable.Dispose()
                  70         {
                  71         }
                  72 
                  73         // Properties
                  74         string IEnumerator<string>.Current
                  75         {
                  76             [DebuggerHidden]
                  77             get
                  78             {
                  79                 return this.<>2__current;
                  80             }
                  81         }
                  82 
                  83         object IEnumerator.Current
                  84         {
                  85             [DebuggerHidden]
                  86             get
                  87             {
                  88                 return this.<>2__current;
                  89             }
                  90         }
                  91     }
                  92 }

                  有趣的是編譯器用switch case 實現MoveNext方法,yield用狀態機實現迭代器。

                  三、理解yield關鍵字

                  yield關鍵字,后面緊跟return 表達式或者break。return 表達式,并沒有結束迭代器,只是暫時離開迭代器,在特定情況下(調用MoveNext方法時),又會進入迭代器??梢岳斫獾魈幱跁和;蛘邟炱馉顟B。break直接結束迭代。

                  四、迭代器的其它用途

                  Linq表達式的延遲加載,如果我們有一個數組,想通過Linq過濾一下:

                   

                    List<int> ages =new List<int> { 5, 17, 30, 40 };
                    var yong = ages.Where(g => g < 18);
                  
                    ages.Add(2);
                  
                     foreach (var item in yong)
                     {
                        Console.WriteLine(item);
                     }

                   

                  運行結果:

                   

                  Where擴展方法只是生成了一個迭代器,告訴這個迭代器原始的集合,以及如何篩選的方法,到調用的時候,才真正的過濾數據,這就是Linq延遲加載的原理。

                   

                  隨時隨地學軟件編程-關注百度小程序和微信小程序
                  關于找一找教程網

                  本站文章僅代表作者觀點,不代表本站立場,所有文章非營利性免費分享。
                  本站提供了軟件編程、網站開發技術、服務器運維、人工智能等等IT技術文章,希望廣大程序員努力學習,讓我們用科技改變世界。
                  [迭代器模式隨想]http://www.yachtsalesaustralia.com/tech/detail-90367.html

                  贊(0)
                  關注微信小程序
                  程序員編程王-隨時隨地學編程

                  掃描二維碼或查找【程序員編程王】

                  可以隨時隨地學編程啦!

                  技術文章導航 更多>
                  国产在线拍揄自揄视频菠萝

                        1. <dd id="erndk"></dd>