如果要迭代一个类,可使用GetEnumerator()方法,其返回值类型是IEnumerator,可以让该类继承IEnumerator, IEnumerable这两个接口,foreach语句隐式地调用了集合的无参数GetEnumerator方法以获得一个枚举器,
我找了一个曾经做过的例子:
Code
1 public class ProviderSet : DataTable, IEnumerable, IEnumerator
2 {
3 #region Constants
4 const string SP_GET_PROVIDERS_BY_PRACTICE = "h2o_ProviderGetProvidersByPractice ";
5 const string SP_GET_PROVIDERS_BY_PATIENT = "h2o_ProviderGetProvidersByPatient ";
6 #endregion //Constants
7
8 #region Enumerations
9 /// <summary>
10 /// //Errors returned from h2o_PatientGetPatientAndDependents stored procedure.
11 /// </summary>
12 private enum h2o_ProviderGetProvidersByPatientEnum
13 {
14 RET_OK = 0,
15 RET_BAD_PARAM_ID = -1
16 }
17
18 #endregion
19
20 #region Member Variables
21 int _enumeratorPosition = -1;
22 #endregion //Member Variables
23
24 #region Constructors
25 /// <summary>
26 /// This <c>ProviderSet</c> constructor creates an empty ProviderSet object that has not been filled with data.
27 /// </summary>
28 /// <example> This sample shows how to create a ProviderSet object using this constructor.
29 /// <code>
30 /// class ExampleClass
31 /// {
32 /// public int Main()
33 /// {
34 /// ProviderSet oProviderSet = new ProviderSet();
35 /// }
36 /// }
37 /// </code>
38 /// </example>
39 public ProviderSet() {}
40
41 /// <summary>
42 /// This <c>ProviderSet</c> constructor initializes the ProviderSet object by providing it with a SQL statement, Parameter array
43 /// and connection string so that it can fill itself with data.
44 /// </summary>
45 /// <param name="sql">This string parameter represents the stored procedure name or SQL statement.</param>
46 /// <param name="paramList">This IDbDataParameter array parameter is a list of either
47 /// SqlParameter or OleDbParameter objects.</param>
48 /// <example> This sample shows how to create a ProviderSet object using this constructor.
49 /// <code>
50 /// class ExampleClass
51 /// {
52 /// public int Main()
53 /// {
54 /// string sql = "sp_get_some_data";
55 ///
56 /// DataParameterList oParamList = new DataParameterList(1);
57 /// oParamList.AddSqlParameter("@providerID", 1, SqlDbType.Int);
58 ///
59 /// ProviderSet oProviderSet = new ProviderSet(sql, oParamList);
60 /// Console.Write("Number of Providers is " + oProviderSet.Count.ToString());
61 /// }
62 /// }
63 /// </code>
64 /// </example>
65 public ProviderSet(string sql, DataParameterList paramList)
66 {
67 Fill(sql, paramList);
68 }
69 #endregion //Constructors
70
71 #region Public Instance Methods
72 /// <summary>
73 /// The <c>Fill</c> method fills the ProviderSet object with data by providing it with a SQL statement, Parameter array
74 /// and connection string.
75 /// </summary>
76 /// <param name="sql">This string parameter represents the stored procedure name or SQL statement.</param>
77 /// <param name="paramList">This IDbDataParameter array parameter is a list of either
78 /// SqlParameter or OleDbParameter objects.</param>
79 /// <example> This sample shows how to call the Fill method.
80 /// <code>
81 /// class ExampleClass
82 /// {
83 /// public int Main()
84 /// {
85 /// string sql = "sp_get_some_data";
86 ///
87 /// DataParameterList oParamList = new DataParameterList(1);
88 /// oParamList.AddSqlParameter("@providerID", 1, SqlDbType.Int);
89 ///
90 /// ProviderSet oProviderSet = new ProviderSet();
91 /// oProviderSet.Fill(sql, oParamList);
92 ///
93 /// Console.Write("Number of Providers is " + oProviderSet.Count.ToString());
94 /// }
95 /// }
96 /// </code>
97 /// </example>
98 public void Fill(string sql, DataParameterList paramList)
99 {
100 Dac.FillDataTable((DataTable)this, sql, paramList, 0);
101 }
102 #endregion //Public Instance Methods
103
104 #region Public Static Methods
105 /// <summary>
106 /// The static <c>GetProvidersByPractice</c> method creates a ProviderSet object containing information for all the Providers linked to a Clinic.
107 /// </summary>
108 /// <param name="practiceId">This int parameter the ID of the Clinic that is being queried for.</param>
109 /// <example> This sample shows how to call the GetProvidersByPractice method.
110 /// <code>
111 /// class ExampleClass
112 /// {
113 /// public int Main()
114 /// {
115 /// int clinicID = 1;
116 ///
117 /// ProviderSet oProviderSet = ProviderSet.GetProvidersByPractice(clinicID);
118 ///
119 /// Console.Write("Number of Providers is " + oProviderSet.Count.ToString());
120 /// }
121 /// }
122 /// </code>
123 /// </example>
124 public static ProviderSet GetProvidersByPractice(int practiceId)
125 {
126 DataParameterList paramList = new DataParameterList(1);
127 paramList.AddSqlParameter("@practiceID", practiceId, SqlDbType.Int);
128
129 return new ProviderSet(SP_GET_PROVIDERS_BY_PRACTICE, paramList);
130 }
131
132 /// <summary>
133 /// The static <c>GetProvidersByPatient</c> method creates a ProviderSet object containing information for all the Providers linked to a Patient.
134 /// </summary>
135 /// <param name="patientId">This int parameter the ID of the Clinic that is being queried for.</param>
136 /// <example> This sample shows how to call the GetProvidersByPatient method.
137 /// <code>
138 /// class ExampleClass
139 /// {
140 /// public int Main()
141 /// {
142 /// int patientID = 1;
143 ///
144 /// ProviderSet oProviderSet = ProviderSet.GetProvidersByPatient(patientID);
145 ///
146 /// Console.Write("Number of Providers is " + oProviderSet.Count.ToString());
147 /// }
148 /// }
149 /// </code>
150 /// </example>
151 public static ProviderSet GetProvidersByPatient(int patientId)
152 {
153 DataParameterList paramList = new DataParameterList(1);
154 paramList.AddSqlParameter("@patientID", patientId, SqlDbType.Int);
155 ProviderSet providerSet = new ProviderSet();
156 Dac.FillDataTable((DataTable)providerSet, SP_GET_PROVIDERS_BY_PATIENT, paramList, 0);
157
158 switch ((h2o_ProviderGetProvidersByPatientEnum)paramList.ReturnValue)
159 {
160 case h2o_ProviderGetProvidersByPatientEnum.RET_OK:
161 return providerSet;
162 case h2o_ProviderGetProvidersByPatientEnum.RET_BAD_PARAM_ID:
163 throw new ApplicationException("The ID parameter supplied to the procedure was invalid.");
164 default:
165 throw new ApplicationException("A SQL error occured while retrieving the set of dependents. SQL error number = " + paramList.ReturnValue.ToString());
166 }
167
168 }
169
170 #endregion //Public Static Methods
171
172 #region Properties
173 /// <summary>
174 /// The read-only <c>Count</c> property returns the number of Providers contained in the current instance of the ProviderSet object.
175 /// </summary>
176 /// <example> This sample shows how to access the Count property.
177 /// <code>
178 /// class ExampleClass
179 /// {
180 /// public int Main()
181 /// {
182 /// int providerID = 1;
183 ///
184 /// ProviderSet oProviderSet = ProviderSet.GetPatients(providerID);
185 ///
186 /// Console.Write("Number of Providers is " + oProviderSet.Count.ToString());
187 /// }
188 /// }
189 /// </code>
190 /// </example>
191 public int Count { get { return this.Rows.Count; } }
192 #endregion //Properties
193
194 #region Interface Methods
195 /// <summary>
196 /// The <c>GetEnumerator</c> method provides a simple "foreach" style iteration over the ProviderStructs in the ProviderSet.
197 /// </summary>
198 public IEnumerator GetEnumerator()
199 {
200 return (IEnumerator)this;
201 }
202
203 /// <summary>
204 /// The <c>MoveNext</c> method advances the enumerator to the next ProviderStruct in the ProviderSet.
205 /// </summary>
206 public bool MoveNext()
207 {
208 _enumeratorPosition++;
209
210 if (_enumeratorPosition < this.Rows.Count - 1)
211 return true;
212 else
213 return false;
214 }
215
216 /// <summary>
217 /// The <c>Reset</c> method sets the enumerator to its initial position, which is before the first ProviderStruct in the ProviderSet.
218 /// </summary>
219 public new void Reset()
220 {
221 _enumeratorPosition = -1;
222 }
223
224 /// <summary>
225 /// The <c>Current</c> property gets the current ProviderStruct in the ProviderSet.
226 /// </summary>
227 public object Current
228 {
229 get {
230 DataRow dataRow = this.Rows[_enumeratorPosition];
231
232 return new ProviderStruct(int.Parse(dataRow["Provider"].ToString()),
233 dataRow["First_Name"].ToString(),
234 dataRow["Last_Name"].ToString());
235 }
236 }
237 #endregion //Interface Methods
238 }
由集合所定义的只能有一个这样的无参数
GetEnumerator方法,但经常有多种枚举方式,以及通过参数控制枚举的方法。在这种情况下,集合可以使用迭代器实现返回可枚举接口之一的属性和方法。如下:
1 class MusicTitles
2 {
3 string[] names = {
4 "Tubular Bells",
5 "Hergest Ridge",
6 "Ommadawn",
7 "Platinum"
8 };
9
10 public IEnumerator GetEnumerator()
11 {
12 for (int i = 0; i < 4; i++)
13 {
14 yield return names[i];
15 }
16 }
17
18 public IEnumerable Reverse()
19 {
20 for (int i = 3; i >= 0; i--)
21 {
22 yield return names[i];
23 }
24 }
25
26 public IEnumerable Subset( int index, int length)
27 {
28 for (int i = index; i < index + length; i++)
29 {
30 yield return names[i];
31 }
32 }
33
34 public static void testMusicTitels()
35 {
36 MusicTitles titles = new MusicTitles();
37 foreach (string title in titles)
38 {
39 Console.WriteLine(title);
40 }
41
42 Console.WriteLine();
43 Console.WriteLine("reverse");
44 foreach (string title in titles.Reverse())
45 {
46 Console.WriteLine(title);
47 }
48 Console.WriteLine();
49 Console.WriteLine("subset");
50 foreach (string title in titles.Subset(2, 2))
51 {
52 Console.WriteLine(title);
53 }
54 }
55 }
这个例子改自:c#3.0 高级编程