12.C#yield return和yield break及實際應用小例(六章6.2-6.4)

來源:互聯網
上載者:User

標籤:

  晚上好,各位。今天結合書中所講和MSDN所查,聊下yield關鍵字,它是我們簡化迭代器的關鍵。

  如果你在語句中使用了yield關鍵字,則意味著它在其中出現的方法、運算子或get訪問器是迭代器,通過使用yield定義迭代器,可在實現自訂集合類型的IEnumerable和IEnumerator模式時無需顯示類(保留枚舉狀態類),使用yield有兩種形式,如下

1 yield return 運算式2 yield break

  先說明一下yield return語句,每一次返回一個元素。通過foreach語句或LINQ查詢來使用迭代器方法。foreach迴圈的每次迭代都會調用迭代器方法,會儲存當前返回的狀態。

 1 static void Main(string[] args) 2 { 3     foreach (int i in GetValues()) 4     { 5         Console.WriteLine(i); 6     } 7     Console.ReadKey(); 8 } 9 10 static IEnumerable<int> GetValues()11 {12     yield return 1;13     yield return 2;14     yield return 3;15 }

  不能將yield return語句放在try-catch之中,但可以把它放在try-finally之中。yield return有兩個特點:1.傳回型別必須是IEnumerable、IEnumerator、IEnumerator<T>、IEnumerable<T>.2.不能使用ref和out修飾符。在匿名方法和不安全的程式碼中不能包含yield return和yield break。下面我們使用yield return來簡化上一篇中對Student的迭代,重新個性了Queue<T>這個泛型類,如下

 1 class Queue<T> : IEnumerable<T> where T : class 2 { 3     public List<T> objects = new List<T>(); 4     int startPoint = 0; 5     public Queue(List<T> list) 6     { 7         objects = list; 8     } 9 10     //實現從IEnumerable中的GetEnumerator方法11     /*12         個人覺得這個方法在迭代中只會調用一次,不然每次都返回一個新的QueueIterator<T>對象,位置記錄都會重設為-113     */14     public IEnumerator<T> GetEnumerator()15     {16         //return new QueueIterator<T>(this);  17         for (int index = 0; index < objects.Count; index++)18         {19             20             yield return objects[(index + startPoint) % objects.Count];21         }22     }23 24     IEnumerator IEnumerable.GetEnumerator()25     {26         throw new NotImplementedException();27     }28 }

  代碼到了yield return時,返回objects中一個合適的元素,並儲存當前的狀態,等下一次調用時從記數的位置開始。在使用程式中,如下,和原先一樣。

 1 List<Student> list = new List<Student> { 2     new Student("СA"), 3     new Student("СB"), 4     new Student("СC"), 5     new Student("СD"), 6     new Student("СE") 7 }; 8 ConsoleDemo.Chapter6.Queue<Student> lq = new Chapter6.Queue<Student>(list); 9 10 foreach (var obj in lq)11 {12     obj.SayName();13 }

  可以看到結果都是迭代的列印每一個元素的名字。在來說下return break,從break中可以看中,是跳出,那意思就應該上跳出迭代,如

 1 class Program 2 { 3     static void Main(string[] args) 4     { 5  6         foreach (int i in GetValues()) 7         { 8             Console.WriteLine(i); 9         }10         Console.ReadKey();11     }12 13     static IEnumerable<int> GetValues()14     {15         yield return 1;16         yield return 2;17         yield break;18         yield return 3;19     }20 }

  到了yield return 2時,下一語句是yield break,則在控制台只會列印1,2,因為在列印3之前就使用yield break跳出迭代了。

  下面我們使用一個實際點的讀檔案的例子。建立一個文本demo.txt,內容如下

 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 910 0

  代碼如下

 1 class Program 2 { 3     static void Main(string[] args) 4     { 5         foreach(var line in ReadLines("./demo.txt")) 6         { 7             Console.WriteLine(line); 8         } 9         Console.ReadKey();10     }11 12     static IEnumerable<string> ReadLines(string path)13     {14         string line;15         TextReader tr = File.OpenText(path);16         while ((line = tr.ReadLine()) != null)17         {18             yield return line;19         }20     }21 }

  當然其實File中的表態方法是有ReadLines方法的,返回的也是IEnumerable<string>,看來我們是多此一舉了,不過也不錯,知道了一些yield的使用,原理的那些真心不敢寫,寫了自己也看不懂,希望以後能用自己組織語言,解譯那些原理。

  請斧正。

12.C#yield return和yield break及實際應用小例(六章6.2-6.4)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.