Foreach遍历集合类原理

下面的代码示例阐释如何编写可与 foreach 一起使用的非泛型集合类。 该类是字符串标记化拆分器,类似于 C 运行时函数 strtok_s

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Collections;
 6 
 7 namespace Macaco.Study.ConsoleProject
 8 {
 9     /*
10      * 注意:数组下标在下文中称为“索引”或“索引位置”
11      */
12     public class Each_Inherit:IEnumerable
13     {
14         //创建用于存放字符串的数组
15         private string[] elements;
16 
17         /// <summary>
18         /// 赋值构造
19         /// </summary>
20         /// <param name="source">数据</param>
21         /// <param name="delimiters">分隔符</param>
22         public Each_Inherit(string source, char[] delimiters)
23         {
24             //将字符串按指定的分隔符分割到字符串数组中
25             elements = source.Split(delimiters);
26         }
27 
28         /// <summary>
29         /// 返回一个循环访问集合的枚举器。
30         /// </summary>
31         /// <returns>可用于循环访问集合的 System.Collections.IEnumerator 对象。</returns>
32         public IEnumerator GetEnumerator()
33         {
34             return new Each_InheritEnum(this);
35         }
36 
37         /// <summary>
38         /// 循环访问集合的枚举器类
39         /// </summary>
40         public class Each_InheritEnum:IEnumerator
41         {
42             //创建当前遍的索引位置
43             private int position = -1;
44 
45             //创建要在Foreach中遍历的对象
46             private Each_Inherit ea;
47 
48             /// <summary>
49             /// 赋值构造
50             /// </summary>
51             /// <param name="ea">要在Foreach中遍历的对象</param>
52             public Each_InheritEnum(Each_Inherit ea)
53             {
54                 this.ea = ea;
55             }
56 
57             /// <summary>
58             /// 返回当前索引所对应的对象
59             /// </summary>
60             public object Current
61             {
62                 get { return ea.elements[position]; }
63             }
64 
65             /// <summary>
66             /// 设置下一轮循环的索引位置
67             /// </summary>
68             /// <returns>返回是否继续下一轮循环</returns>
69             public bool MoveNext()
70             {
71                 if (position < ea.elements.Length - 1)
72                 {
73                     position++;
74                     return true;
75                 }
76                 else
77                 {
78                     return false;
79                 }
80             }
81 
82             /// <summary>
83             /// 重置当前索引位置
84             /// </summary>
85             public void Reset()
86             {
87                 position = -1;
88             }
89         }
90     }
91 }
92 

  在 C# 中,集合类不一定要从 IEnumerableIEnumerator 继承以便与 foreach 兼容。 只要此类具有必需的 GetEnumeratorMoveNextResetCurrent 成员,就可 foreach 与一起使用。 省略接口有一个好处:您可以将 Current 的返回类型定义得比 Object 更为明确,从而提供类型安全。

例如以下代码: 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace Macaco.Study.ConsoleProject
 7 {
 8     public class Each_NOInherit
 9     {
10         public string[] elements;
11 
12         public Each_NOInherit(string source,char[] delimiters)
13         {
14             elements = source.Split(delimiters);
15         }
16 
17         /// <summary>
18         /// 返回一个循环访问集合的枚举器。
19         /// </summary>
20         /// <returns>可用于循环访问集合的Each_NoInheritEnum对象。</returns>
21         public Each_NOInheritEnum GetEnumerator()
22         {
23             return new Each_NOInheritEnum(this);
24         }
25 
26         /// <summary>
27         /// 循环访问集合的枚举器类
28         /// </summary>
29         public class Each_NOInheritEnum
30         {
31             private int position=-1;
32 
33             private Each_NOInherit ea;
34 
35             public Each_NOInheritEnum(Each_NOInherit ea)
36             {
37                 this.ea = ea;
38             }
39 
40             /// <summary>
41             /// 返回当前索引所对应的字符串
42             /// </summary>
43             public string Current
44             {
45                 get { return ea.elements[position]; }
46             }
47 
48             public bool MoveNext()
49             {
50                 if (position < ea.elements.Length - 1)
51                 {
52                     position++;
53                     return true;
54                 }
55                 else 
56                 {
57                     return false;
58                 }
59             }
60 
61             public void Resset()
62             {
63                 position = -1;
64             }
65         }
66     }
67 }
68 

 

 

下现是调用这两个集合类的主函数:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace Macaco.Study.ConsoleProject
 7 {
 8     class Program
 9     {
10         static void Main(string[] args)
11         {
12             Each_Test();
13         }
14         private static void Each_Test()
15         {
16             //该类继承自IEnumerable接口,实现接口方法GetEnumerator
17             Each_Inherit ea = new Each_Inherit("This is Each_Inherit Test"new char[] { ' ''_' });
18 
19             Console.WriteLine("-------Inherit Result-------");
20             foreach (string str in ea)
21             {
22                 Console.WriteLine(str);
23             }
24             Console.WriteLine("----------------------------");
25 
26             Console.WriteLine();
27 
28             //该类没有继承自IEnumerable,但是具有GetEnumerator方法
29             Each_NOInherit eaNo = new Each_NOInherit("This is Each_NO_Inherit Test"new char[] { ' ''_' });
30 
31             Console.WriteLine("------No Inherit Result-----");
32             foreach (string str in eaNo)
33             {
34                 Console.WriteLine(str);
35             }
36             Console.WriteLine("----------------------------");
37         }
38         /*OutPut:
39          * -------Inherit Result-------
40          *  This
41          *  is
42          *  Each
43          *  Inherit
44          *  Test
45          * ----------------------------
46          * 
47          * ------No Inherit Result-----
48          *  This
49          *  is
50          *  Each
51          *  NO
52          *  Inherit
53          *  Test
54          * ----------------------------
55          */
56 
57        /* 
58         *第一种:实现IEnumerable和IEnumerator接口
59         *第二种:不实现任何接口,但具备以上两个接口中需要实现的方法
60         *优缺点:
61         *  1.第一种集合类能够与其他公共语言运行时 兼容语言的 foreach 语句或等效项交互操作,而第二种不能。 
62         *  2.第一种集合类不可以将 Current 的返回类型定义得比 Object 更为明确,因此无法提供类型安全,
63         *    而第二种集合类可以将Current的返回定义为string从而能够提供更好的类型安全。
64         */
65     }
66 }
67 

 

阅读更多
个人分类: 常用查询
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭