1. foreach語句
C#編譯器會把foreach語句轉換為IEnumerable接口的方法和屬性。
1 foreach (Person p in persons) 2 { 3 Console.WriteLine(p); 4 }
foreach語句會解析為下面的代碼段。
- 調用GetEnumerator()方法,獲得數組的一個枚舉
- 在while循環中,只要MoveNext()返回true,就一直循環下去
- 用Current屬性訪問數組中的元素
1 IEnumerator enumerator = persons. GetEnumerator(); 2 while (enumerator.MoveNext()) 3 { 4 Person p = (Person) enumerator.Current; 5 Console.WriteLine(p); 6 }
2. yield語句
- yield語句的兩種形式:
1 yield return <expression>; 2 yield break;
- 使用一個yield return語句返回集合的一個元素
- 包含yield語句的方法或屬性是迭代器。迭代器必須滿足以下要求
a. 返回類型必須是IEnumerable、IEnumerable<T>、IEnumerator或 IEnumerator<T>。
b. 它不能有任何ref或out參數
- yield return語句不能位於try-catch快。yield return語句可以位於try-finally的try塊
1 try 2 { 3 // ERROR: Cannot yield a value in the boday of a try block with a catch clause 4 yield return "test"; 5 } 6 catch 7 { } 8 9 try 10 { 11 // 12 yield return "test again"; 13 } 14 finally 15 { } 16 17 try 18 { } 19 finally 20 { 21 // ERROR: Cannot yield in the body of a finally clause 22 yield return ""; 23 }
- yield break語句可以位於try塊或catch塊,但是不能位於finally塊
下面的例子是用yield return語句實現一個簡單集合的代碼,以及用foreach語句迭代集合
1 using System; 2 using System.Collections.Generic; 3 4 namespace ConsoleApplication6 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 HelloCollection helloCollection = new HelloCollection(); 11 foreach (string s in helloCollection) 12 { 13 Console.WriteLine(s); 14 Console.ReadLine(); 15 } 16 } 17 } 18 19 public class HelloCollection 20 { 21 22 public IEnumerator<String> GetEnumerator() 23 { 24 // yield return語句返回集合的一個元素,並移動到下一個元素上;yield break可以停止迭代 25 yield return "Hello"; 26 yield return "World"; 27 } 28 } 29 }
使用yield return語句實現以不同方式迭代集合的類:
1 using System; 2 using System.Collections.Generic; 3 4 namespace ConsoleApplication8 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 MusicTitles titles = new MusicTitles(); 11 foreach (string title in titles) 12 { 13 Console.WriteLine(title); 14 } 15 Console.WriteLine(); 16 17 foreach (string title in titles.Reverse()) 18 { 19 Console.WriteLine(title); 20 } 21 Console.WriteLine(); 22 23 foreach (string title in titles.Subset(2, 2)) 24 { 25 Console.WriteLine(title); 26 Console.ReadLine(); 27 } 28 } 29 } 30 31 public class MusicTitles 32 { 33 string[] names = { "a", "b", "c", "d" }; 34 public IEnumerator<string> GetEnumerator() 35 { 36 for (int i = 0; i < 4; i++) 37 { 38 yield return names[i]; 39 } 40 } 41 42 public IEnumerable<string> Reverse() 43 { 44 for (int i = 3; i >= 0; i--) 45 { 46 yield return names[i]; 47 } 48 } 49 50 public IEnumerable<string> Subset(int index, int length) 51 { 52 for (int i = index; i < index + length; i++) 53 { 54 yield return names[i]; 55 } 56 } 57 } 58 }
輸出: