使用迭代器做自定义筛选

时间:2022-02-13 23:22:43
  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 }