C#知識點-枚舉器和迭代器


一、幾個基本概念的理解

問題一:為什么數組可以使用foreach輸出各元素

答:數組是可枚舉類型,它實現了一個枚舉器(enumerator)對象;枚舉器知道各元素的次序並跟蹤它們的位置,然后返回請求的當前項

問題二:不用foreach能不能遍歷各元素

image

問題三:什么是可枚舉類

答:可枚舉類是指實現了IEnumerable接口的類;IEnumerable接口只有一個成員GetEnumerator方法,它返回對象的枚舉器

問題四:什么是枚舉器

答:實現了IEnumerator接口的枚舉器包含三個函數成員:Current,MoveNext,Reset

Current是只讀屬性,它返回object類型的引用;

MoveNext是把枚舉器位置前進到集合的下一項的方法,它返回布爾值,指示新的位置是否有效位置還是已經超過了序列的尾部;

Reset是把位置重置為原始狀態的方法;

二、下面代碼展示了一個可枚舉類的完整示例

  1 namespace ConsoleApplication4
  2 {
  3     /// <summary>
  4     /// 自定義一個枚舉對象
  5     /// </summary>
  6     class ColorEnumerator : IEnumerator
  7     {
  8         private string[] _colors;
  9         private int _position = -1;
 10 
 11         public ColorEnumerator(string[] arr)
 12         {
 13             _colors = arr;
 14             for (int i = 0; i < arr.Length; i++)
 15             {
 16                 _colors[i] = arr[i];
 17             }
 18         }
 19         public object Current
 20         {
 21             get
 22             {
 23                 if (_position == -1)
 24                 {
 25                     throw new InvalidOperationException();
 26                 }
 27                 if (_position >= _colors.Length)
 28                 {
 29                     throw new InvalidOperationException();
 30                 }
 31                 return _colors[_position];
 32             }
 33         }
 34 
 35         public bool MoveNext()
 36         {
 37             if (_position < _colors.Length - 1)
 38             {
 39                 _position++;
 40                 return true;
 41             }
 42             else
 43             {
 44                 return false;
 45             }
 46         }
 47 
 48         public void Reset()
 49         {
 50             _position = -1;
 51         }
 52     }
 53 
 54     /// <summary>
 55     /// 創建一個實現IEnumerable接口的枚舉類
 56     /// </summary>
 57     class Spectrum : IEnumerable
 58     {
 59         private string[] Colors = { "red", "yellow", "blue" };
 60         public IEnumerator GetEnumerator()
 61         {
 62             return new ColorEnumerator(Colors);
 63         }
 64     }
 65 
 66     class Program
 67     {
 68         static void Main(string[] args)
 69         {
 70             Spectrum spectrum = new Spectrum();
 71             foreach (string color in spectrum)
 72             {
 73                 Console.WriteLine(color);
 74             }
 75             Console.ReadKey();
 76         }
 77     }
 78 }
 79 
View Code

三、泛型枚舉接口

IEnumerable<T>接口的GetEnumerator方法返回實現IEnumerator<T>的枚舉類的實例;

實現IEnumerator<T>的類實現了Current屬性,它返回實際類型的對象,而不是object基類的引用;

所以非泛型接口的實現不是類型安全的,因為還需要轉換為實際類型。

四、迭代器

1.使用迭代器來創建枚舉器

  1 namespace ConsoleApplication5
  2 {
  3     class MyClass
  4     {
  5         /// <summary>
  6         /// 獲取一個迭代器
  7         /// </summary>
  8         /// <returns></returns>
  9         public IEnumerator<string> GetEnumerator()
 10         {
 11             return ColorEnumerator();
 12         }
 13         /// <summary>
 14         /// 迭代器
 15         /// </summary>
 16         /// <returns></returns>
 17         public IEnumerator<string> ColorEnumerator()
 18         {
 19             yield return "red";
 20             yield return "yellow";
 21             yield return "blue";
 22         } 
 23     }
 24     class Program
 25     {
 26         static void Main(string[] args)
 27         {
 28             MyClass mc = new MyClass();
 29             foreach (string color in mc)
 30             {
 31                 Console.WriteLine(color);
 32             }
 33             Console.ReadKey();
 34         }
 35     }
 36 }
View Code

2.使用迭代器來創建枚舉類型

  1 namespace ConsoleApplication6
  2 {
  3     class MyClass
  4     {
  5         public IEnumerator<string> GetEnumerator()
  6         {
  7             //獲取可枚舉類型
  8             IEnumerable<string> enumerable = ColorEnumerable();
  9             //獲取枚舉器
 10             return ColorEnumerable().GetEnumerator();
 11         }
 12 
 13         public IEnumerable<string> ColorEnumerable()
 14         {
 15             yield return "red";
 16             yield return "yellow";
 17             yield return "blue";
 18         } 
 19     }
 20     class Program
 21     {
 22         static void Main(string[] args)
 23         {
 24             MyClass mc = new MyClass();
 25             //使用類對象
 26             foreach (string color in mc)
 27             {
 28                 Console.WriteLine(color);
 29             }
 30             Console.WriteLine("-----------------------");
 31             //使用類枚舉器的方法
 32             foreach (string color in mc.ColorEnumerable())
 33             {
 34                 Console.WriteLine(color);
 35             }
 36             Console.ReadKey();
 37         }
 38     }
 39 }
View Code

3.產生多個可迭代類型

  1 namespace ConsoleApplication7
  2 {
  3     class MyClass
  4     {
  5         private string[] Colors = { "red", "yellow", "blue" };
  6         //順序
  7         public IEnumerable<string> ColorOrder()
  8         {
  9             for (int i = 0; i < Colors.Length; i++)
 10             {
 11                 yield return Colors[i];
 12             }
 13         }
 14         //逆序
 15         public IEnumerable<string> ColorReversed()
 16         {
 17             for (int i = Colors.Length - 1; i >= 0; i--)
 18             {
 19                 yield return Colors[i];
 20             }
 21         }
 22     }
 23     class Program
 24     {
 25         static void Main(string[] args)
 26         {
 27             MyClass mc = new MyClass();
 28             foreach (string color in mc.ColorOrder())
 29             {
 30                 Console.WriteLine(color);
 31             }
 32             Console.WriteLine("------------------");
 33             foreach (string color in mc.ColorReversed())
 34             {
 35                 Console.WriteLine(color);
 36             }
 37             Console.ReadKey();
 38         }
 39     }
 40 }
 41 
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM