下面的代码示例阐释如何编写可与 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
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# 中,集合类不一定要从 IEnumerable 和 IEnumerator 继承以便与 foreach 兼容。 只要此类具有必需的 GetEnumerator、 MoveNext、 Reset 和 Current 成员,就可 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
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
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