程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 12.C#yield return和yield break及實際應用小例(六章6.2-6.4),

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

編輯:C#入門知識

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


  晚上好,各位。今天結合書中所講和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>對象,位置記錄都會重置為-1
13     */
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 9
10 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的使用,原理的那些真心不敢寫,寫了自己也看不懂,希望以後能用自己組織語言,解譯那些原理。

  請斧正。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved