原文:
C#:foreach语句,yield语句
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 }
输出: