1. 程式人生 > >使用迭代器做自定義篩選

使用迭代器做自定義篩選

  1 /*
  2  IEnumerator 介面
  3 支援對非泛型集合的簡單迭代。 
  4 
  5 IEnumerator 是所有非泛型列舉數的基介面。
  6 
  7 
  8 C# 語言的 foreach 語句(在 Visual Basic 中為 for each)隱藏了列舉數的複雜性。
  9 
 10 列舉數可用於讀取集合中的資料,但不能用於修改基礎集合。
 11 
 12 最初,列舉數定位在集合中第一個元素前。Reset 方法還會將列舉數返回到此位置。在此位置,呼叫 Current 屬性會引發異常。因此,在讀取 Current 的值之前,必須呼叫 MoveNext 方法將列舉數提前到集合的第一個元素。
13 14 在呼叫 MoveNext 或 Reset 之前,Current 返回同一物件。MoveNext 將 Current 設定為下一個元素。 15 16 如果 MoveNext 越過集合的末尾,則列舉數將被放置在此集合中最後一個元素的後面,而且 MoveNext 返回 false。當列舉數位於此位置時,對 MoveNext 的後續呼叫也返回 false。如果最後一次呼叫 MoveNext 返回 false,則呼叫 Current 會引發異常。若要再次將 Current 設定為集合的第一個元素,可以呼叫 Reset,然後再呼叫 MoveNext。 17 18 只要集合保持不變,列舉數就保持有效。如果對集合進行了更改(如新增、修改或刪除元素),則列舉數將失效且不可恢復,並且下一次對 MoveNext 或 Reset 的呼叫將引發 InvalidOperationException。如果在 MoveNext 和 Current 之間修改集合,那麼即使列舉數已經無效,Current 也將返回它所設定成的元素。
19 20 列舉數沒有對集合的獨佔訪問權;因此,列舉通過集合在本質上不是一個執行緒安全的過程。即使一個集合已進行同步,其他執行緒仍可以修改該集合,這將導致列舉數引發異常。若要在列舉過程中保證執行緒安全,可以在整個列舉過程中鎖定集合,或者捕捉由於其他執行緒進行的更改而引發的異常。 21 */ 22 23 24 using System; 25 using System.Collections.Generic; 26 using System.Collections; 27 using System.Linq; 28 using System.Text; 29 30 namespace
ConsoleApplication1 31 { 32 public class Person 33 { 34 public Person(string fName, string lName) 35 { 36 this.firstName = fName; 37 this.lastName = lName; 38 } 39 40 public string firstName; 41 public string lastName; 42 } 43 44 public class People : IEnumerable 45 { 46 private Person[] _people; 47 public People(Person[] pArray) 48 { 49 _people = new Person[pArray.Length]; 50 51 for (int i = 0; i < pArray.Length; i++) 52 { 53 _people[i] = pArray[i]; 54 } 55 } 56 57 public IEnumerator GetEnumerator() 58 { 59 for (int i = 0; i < _people.Length; i++) { 60 yield return _people[i]; 61 } 62 } 63 } 64 65 class App 66 { 67 static void Main() 68 { 69 Person[] peopleArray = new Person[3] 70 { 71 new Person("John", "Smith"), 72 new Person("Jim", "Johnson"), 73 new Person("Sue", "Rabon"), 74 }; 75 76 People peopleList = new People(peopleArray); 77 foreach (Person p in peopleList) 78 Console.WriteLine(p.firstName + " " + p.lastName); 79 80 List<Product> ps = new List<Product>() { 81 new Product(){ ProductName="筆記本", ProductPrice=3000.00M}, 82 new Product(){ ProductName="小本", ProductPrice=2000.00M}, 83 new Product(){ ProductName="小小本", ProductPrice=1900.00M} 84 }; 85 86 87 88 IEnumerable cheaperPs = GetSpecialProduct(ps); 89 90 foreach (var g in cheaperPs) 91 { 92 Console.WriteLine(((Product)g).ProductName + ":" + ((Product)g).ProductPrice); 93 } 94 95 } 96 97 static IEnumerable GetSpecialProduct(List<Product> gs) 98 { 99 foreach (var g in gs) 100 { 101 if (g.ProductPrice <= 2000) 102 { 103 yield return g; 104 } 105 } 106 } 107 108 static List<Product> GetSpecialProductOld(List<Product> gs) 109 { 110 List<Product> pps = new List<Product>(); 111 foreach (var g in gs) 112 { 113 if (g.ProductPrice <= 2000) 114 { 115 pps.Add(g); 116 } 117 } 118 return pps; 119 } 120 121 122 } 123 class Product 124 { 125 public string ProductName 126 { get; set; } 127 public decimal? ProductPrice 128 { 129 get; 130 set; 131 } 132 } 133 134 }