當自定義類需要實現索引時,可以在類中實現索引器。
用Table作為例子,Table由多個Row組成,Row由多個Cell組成,
我們需要實現自定義的table[0],row[0]
索引器定義格式為
[修飾符] 數據類型 this[索引類型 index]
以下是代碼

1 /// <summary>
2 /// 單元格
3 /// </summary>
4 public class Cell
5 {
6 /// <summary>
7 /// Value
8 /// </summary>
9 public object Value { get; set; }
10 /// <summary>
11 /// StringValue
12 /// </summary>
13 public string StringValue { get; set; }
14 }
View Code

1 /// <summary>
2 /// 行
3 /// </summary>
4 public class Row
5 {
6 /// <summary>
7 /// 獲取Row中的Cell數
8 /// </summary>
9 public int Length { get; private set; }
10
11 /// <summary>
12 /// 索引
13 /// </summary>
14 public Cell this[int column]
15 {
16 get
17 {
18 return this[column];
19 }
20 }
21 /// <summary>
22 /// 行
23 /// </summary>
24 /// <param name="values"></param>
25 public Row(object[] values)
26 {
27 this.Length = values.Length;
28 for (int i = 0; i < this.Length; i++)
29 {
30 this[i].Value = values[i];
31 this[i].StringValue = Convert.ToString(values[i]);
32 }
33 }
34 /// <summary>
35 /// 行
36 /// </summary>
37 /// <param name="values"></param>
38 public Row(string[] values)
39 {
40 this.Length = values.Length;
41 for (int i = 0; i < this.Length; i++)
42 {
43 this[i].Value = values[i];
44 this[i].StringValue = values[i];
45 }
46 }
47 /// <summary>
48 /// 行
49 /// </summary>
50 /// <param name="values"></param>
51 public Row(int[] values)
52 {
53 this.Length = values.Length;
54 for (int i = 0; i < this.Length; i++)
55 {
56 this[i].Value = values[i];
57 this[i].StringValue = values[i].ToString();
58 }
59 }
60 }
View Code
這時候,Row就可以有自己的索引了,調用如下

1 public class Test
2 {
3 public Test()
4 {
5 Row row = new Row(new string[] { "姓名", "性別", "工號" });
6 if (row.Length > 2)
7 {
8 row[2].StringValue = "學號";
9 }
10 }
11 }
View Code
但是,Row雖然作為一個Cell的集合,卻不能使用foreach進行遍歷。這時候我們需要讓Row繼承IEnumerable接口,並且實現IEnumerable接口的GetEnumerator()方法,
在public class Row : IEnumerable { }中添加如下代碼:

1 /// <summary>
2 /// 實現GetEnumerator()方法
3 /// </summary>
4 /// <returns></returns>
5 public IEnumerator GetEnumerator()
6 {
7 for (int i = 0; i < this.Length; i++)
8 {
9 yield return this[i];
10 }
11 }
View Code
這樣,在調用的時候就能使用foreach遍歷了。
Table和Row的關系同理。
同樣,我們還可以繼承ICollection<T>, IEnumerable<T>, IList<T>等接口,實現相關接口的方法,就可以打造屬於自己的集合了。
一個完整的Demo如下:

1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Diagnostics;
5 using System.Text;
6
7 namespace MyCollection
8 {
9 /// <summary>
10 /// 表示 Cell 集合
11 /// </summary>
12 [DebuggerDisplay("Count = {Count}")]
13 [Serializable]
14 public class MyCollection : IEnumerable, IEnumerable<Cell>, ICollection<Cell>, IList<Cell>
15 {
16 #region 字段
17
18 /// <summary>
19 /// 表示空的 Row 圖層的數組。
20 /// </summary>
21 private readonly static Row[] emptyArray = null;
22
23 /// <summary>
24 /// 存儲 Row 圖層的數組。
25 /// </summary>
26 private Row[] items = null;
27
28 /// <summary>
29 /// 當前 Row 圖層的集合的元素數。
30 /// </summary>
31 private int count = 0;
32
33 #endregion
34
35 #region 屬性
36
37 /// <summary>
38 /// 獲取或設置該 Row 的元素總數。
39 /// </summary>
40 /// <exception cref="System.ArgumentOutOfRangeException">MyCollection.Capacity 設置為小於 MyCollection.Count 的值。</exception>
41 private int Capacity
42 {
43 get
44 {
45 return this.items.Length;
46 }
47 set
48 {
49 if (value != this.items.Length)
50 {
51 if (value < this.count)
52 {
53 throw new ArgumentOutOfRangeException("Capacity", "MyCollection.Capacity 設置為小於 MyCollection.Count 的值。");
54 }
55 if (value > 0)
56 {
57 Row[] destArray = new Row[value];
58 if (this.count > 0)
59 {
60 Array.Copy(this.items, 0, destArray, 0, this.count);
61 }
62 this.items = destArray;
63 }
64 else
65 {
66 this.items = emptyArray;
67 }
68 }
69 }
70 }
71
72 #endregion
73
74 #region 構造函數
75 /// <summary>
76 /// 對 LayerCollection 類進行初始化。
77 /// </summary>
78 static MyCollection()
79 {
80 emptyArray = new Row[0];
81 }
82
83 /// <summary>
84 /// 初始化 HuaXing.ExamOperation.SimulateFlash.LayerCollection 類的新實例。<para/>
85 /// 表示 Layer 圖層的集合。
86 /// </summary>
87 public MyCollection()
88 {
89 this.items = emptyArray;
90 }
91 #endregion
92
93 #region IList<Row> 成員
94
95 #region IndexOf
96
97 /// <summary>
98 /// 搜索指定的 Row 對象,並返回整個 MyCollection 中第一個匹配項的從零開始的索引。
99 /// </summary>
100 /// <param name="item">要在 MyCollection 中定位的 Row 對象。</param>
101 /// <returns>如果在 MyCollection 中找到 item 的第一個匹配項,則為該項的從零開始的索引;否則為-1。</returns>
102 public int IndexOf(Row item)
103 {
104 return Array.IndexOf<Row>(this.items, item, 0, this.count);
105 }
106
107 /// <summary>
108 /// 搜索指定的 Row 對象,並返回整個 MyCollection 中從指定索引到最後一個元素的元素范圍內第一個匹配項的從零開始的索引。
109 /// </summary>
110 /// <param name="item">要在 MyCollection 中定位的 Row 對象。</param>
111 /// <param name="index">從零開始的搜索的起始索引。</param>
112 /// <returns>如果在 MyCollection 中從 index 到最後一個元素的元素范圍內找到 item 的第一個匹配項,則為該項的從零開始的索引;否則為-1。</returns>
113 /// <exception cref="System.ArgumentOutOfRangeException">index 不在 MyCollection 的有效索引范圍內。</exception>
114 public int IndexOf(Row item, int index)
115 {
116 if (index < 0 || index > this.count)
117 {
118 throw new ArgumentOutOfRangeException("index", "index 不在 MyCollection 的有效索引范圍內。");
119 }
120 return Array.IndexOf<Row>(this.items, item, index, this.count - index);
121 }
122
123 /// <summary>
124 /// 搜索指定的 Row 對象,並返回整個 MyCollection 中從指定的索引開始並包含指定的元素數的元素范圍內第一個匹配項的從零開始的索引。
125 /// </summary>
126 /// <param name="item">要在 MyCollection 中定位的 Row 對象。</param>
127 /// <param name="index">從零開始的搜索的起始索引。</param>
128 /// <param name="count">要搜索的部分中的元素數。</param>
129 /// <returns>如果在 MyCollection 中從 index 開始並包含 count 個元素的元素范圍內找到 item 的第一個匹配項,則為該項的從零開始的索引;否則為-1。</returns>
130 /// <exception cref="System.ArgumentOutOfRangeException">index 不在 MyCollection 的有效索引范圍內 或 count 小於 0 或 index 和 count 未指定 MyCollection 中的有效部分。</exception>
131 public int IndexOf(Row item, int index, int count)
132 {
133 if (index < 0 || index > this.count)
134 {
135 throw new ArgumentOutOfRangeException("index", "index 不在 MyCollection 的有效索引范圍內。");
136 }
137 if ((count < 0) || (index > (this.count - count)))
138 {
139 throw new ArgumentOutOfRangeException("count", "count 小於 0 或 index 和 count 未指定 MyCollection 中的有效部分。");
140 }
141 return Array.IndexOf<Row>(this.items, item, index, count);
142 }
143
144 #endregion
145
146 #region Insert
147
148 /// <summary>
149 /// 將 Row 對象插入 MyCollection 的指定索引處。
150 /// </summary>
151 /// <param name="index">從零開始的索引,應在該位置插入 item。</param>
152 /// <param name="item">要插入的 Row 對象。</param>
153 /// <exception cref="System.ArgumentOutOfRangeException">index 小於 0 或 index 大於 MyCollection.Count。</exception>
154 public void Insert(int index, Row item)
155 {
156 if (index < 0 || index > this.count)
157 {
158 throw new ArgumentOutOfRangeException("index", "index 小於 0 或 index 大於 MyCollection.Count。");
159 }
160 if (this.count == this.items.Length)
161 {
162 this.EnsureCapacity(this.count + 1);
163 }
164 if (index < this.count)
165 {
166 Array.Copy(this.items, index, this.items, index + 1, this.count - index);
167 }
168 this.items[index] = item;
169 this.count++;
170 }
171
172 #endregion
173
174 #region RemoveAt
175
176 /// <summary>
177 /// 移除 MyCollection 的指定索引處的 Row 對象。
178 /// </summary>
179 /// <param name="index">要移除的 Row 對象的從零開始的索引。</param>
180 /// <exception cref="System.ArgumentOutOfRangeException">index 小於 0 或 index 等於或大於 MyCollection.Count。</exception>
181 public void RemoveAt(int index)
182 {
183 if (index < 0 || index >= this.count)
184 {
185 throw new ArgumentOutOfRangeException("index", "index 小於 0 或 index 等於或大於 MyCollection.Count。");
186 }
187 this.count--;
188 if (index < this.count)
189 {
190 Array.Copy(this.items, index + 1, this.items, index, this.count - index);
191 }
192 this.items[this.count] = default(Row);
193 }
194
195 #endregion
196
197 #region Item[Int32]
198
199 /// <summary>
200 /// 獲取或設置指定索引處的 Row 對象。
201 /// </summary>
202 /// <param name="index">要獲取或設置的 Row 對象從零開始的索引。</param>
203 /// <returns>指定索引處的 Row 對象。</returns>
204 /// <exception cref="System.ArgumentOutOfRangeException">index 小於 0 或 index 等於或大於 MyCollection.Count。</exception>
205 public Row this[int index]
206 {
207 get
208 {
209 if (index < 0 && index >= this.count)
210 {
211 throw new ArgumentOutOfRangeException("index", "index 小於 0 或 index 等於或大於 MyCollection.Count。");
212 }
213 else
214 {
215 return this.items[index];
216 }
217 }
218 set
219 {
220 if (index < 0 && index >= this.count)
221 {
222 throw new ArgumentOutOfRangeException("index", "index 小於 0 或 index 等於或大於 MyCollection.Count。");
223 }
224 else
225 {
226 this.items[index] = value;
227 }
228 }
229 }
230
231 #endregion
232
233 #endregion
234
235 #region ICollection<Row> 成員
236
237 #region Add
238
239 /// <summary>
240 /// 將 Row 對象,添加到 MyCollection 的結尾處。
241 /// </summary>
242 /// <param name="item">要添加到 MyCollection 的末尾處的 Row 對象。</param>
243 public void Add(Row item)
244 {
245 if (this.count == this.items.Length)
246 {
247 this.EnsureCapacity(this.count + 1);
248 }
249 this.items[this.count++] = item;
250 }
251
252 #endregion
253
254 #region Clear
255
256 /// <summary>
257 /// 從 MyCollection 集合中移除所有元素。
258 /// </summary>
259 public void Clear()
260 {
261 if (this.count > 0)
262 {
263 Array.Clear(this.items, 0, this.count);
264 this.count = 0;
265 }
266 }
267
268 #endregion
269
270 #region Contains
271
272 /// <summary>
273 /// 確定 MyCollection 集合中,是否包含特定值。
274 /// </summary>
275 /// <param name="value">要在 MyCollection 集合中查找的 Row。</param>
276 /// <returns>如果在 MyCollection 集合中找到 Row,則為true;否則為false。</returns>
277 public bool Contains(Row value)
278 {
279 if (value == null)
280 {
281 for (int j = 0; j < this.count; j++)
282 {
283 if (this.items[j] == null)
284 {
285 return true;
286 }
287 }
288 return false;
289 }
290 EqualityComparer<Row> comparer = EqualityComparer<Row>.Default;
291 for (int i = 0; i < this.count; i++)
292 {
293 if (comparer.Equals(this.items[i], value))
294 {
295 return true;
296 }
297 }
298 return false;
299 }
300
301 #endregion
302
303 #region CopyTo
304
305 /// <summary>
306 /// 將整個 MyCollection 復制到一維數組中,從目標數組的開頭開始放置。
307 /// </summary>
308 /// <param name="array">作為從 MyCollection 復制的元素的目標位置的一維數組。</param>
309 /// <exception cref="System.ArgumentException">源 MyCollection 中的元素數大於目標 array 可包含的元素數。</exception>
310 /// <exception cref="System.ArgumentNullException">array 為 null。</exception>
311 public void CopyTo(Row[] array)
312 {
313 this.CopyTo(array, 0);
314 }
315
316 /// <summary>
317 /// 將整個 MyCollection 復制到一維數組中,從目標數組的指定索引位置開始放置。
318 /// </summary>
319 /// <param name="array">作為從 MyCollection 復制的元素的目標位置的一維數組。</param>
320 /// <param name="arrayIndex">array 中從零開始的索引,在此處開始復制。</param>
321 /// <exception cref="System.ArgumentException">arrayIndex 等於或大於 array 的長度 或 源 MyCollection 中的元素數目大於從 arrayIndex 到目標 array 末尾之間的可用空間。</exception>
322 /// <exception cref="System.ArgumentNullException">array 為 null。</exception>
323 /// <exception cref="System.ArgumentOutOfRangeException">arrayIndex 小於 0。</exception>
324 public void CopyTo(Row[] array, int arrayIndex)
325 {
326 Array.Copy(this.items, 0, array, arrayIndex, this.count);
327 }
328
329 /// <summary>
330 /// 將一定范圍的元素從 MyCollection 復制到一維數組中,從目標數組的指定索引位置開始放置。
331 /// </summary>
332 /// <param name="index">源 MyCollection 中復制開始位置的從零開始的索引。</param>
333 /// <param name="array">作為從 MyCollection 復制的元素的目標位置的一維數組。</param>
334 /// <param name="arrayIndex">array 中從零開始的索引,在此處開始復制。</param>
335 /// <param name="count">要復制的元素數。</param>
336 /// <exception cref="System.ArgumentException">index 等於或大於源 MyCollection 的 MyCollection.Count 或 arrayIndex 等於或大於 array 的長度 或 從 index 到源 MyCollection 的末尾的元素數大於從 arrayIndex 到目標 array 的末尾的可用空間。</exception>
337 /// <exception cref="System.ArgumentNullException">array 為 null。</exception>
338 /// <exception cref="System.ArgumentOutOfRangeException">index 小於 0 或 arrayIndex 小於 0 或 count 小於 0。</exception>
339 public void CopyTo(int index, Row[] array, int arrayIndex, int count)
340 {
341 if ((this.count - index) < count)
342 {
343 throw new ArgumentException("index 等於或大於源 MyCollection 的 MyCollection.Count 或 arrayIndex 等於或大於 array 的長度 或 從 index 到源 MyCollection 的末尾的元素數大於從 arrayIndex 到目標 array 的末尾的可用空間。", "index");
344 }
345 Array.Copy(this.items, index, array, arrayIndex, count);
346 }
347
348 #endregion
349
350 #region Count
351
352 /// <summary>
353 /// 獲取當前 Row 集合的元素數。
354 /// </summary>
355 public int Count
356 {
357 get
358 {
359 return this.count;
360 }
361 }
362
363 #endregion
364
365 #region IsReadOnly
366
367 /// <summary>
368 /// 獲取一個值,該值指示 MyCollection 是否為只讀。
369 /// </summary>
370 bool ICollection<Row>.IsReadOnly
371 {
372 get
373 {
374 return false;
375 }
376 }
377
378 #endregion
379
380 #region Remove
381
382 /// <summary>
383 /// 從 MyCollection 中移除特定 Row 對象的第一個匹配項。
384 /// </summary>
385 /// <param name="item">要從 MyCollection 中移除的 Row 對象。</param>
386 /// <returns>如果成功移除 item,則為 true;否則為 false。如果在 MyCollection 中沒有找到 item,該方法也會返回 false。</returns>
387 public bool Remove(Row item)
388 {
389 int index = this.IndexOf(item);
390 if (index >= 0)
391 {
392 this.RemoveAt(index);
393 return true;
394 }
395 return false;
396 }
397
398 #endregion
399
400 #endregion
401
402 #region IEnumerable<Row> 成員
403
404 public IEnumerator<Row> GetEnumerator()
405 {
406 for (int index = 0; index < this.count; index++)
407 {
408 yield return this.items[index];
409 }
410 }
411
412 #endregion
413
414 #region IEnumerable 成員
415
416 IEnumerator IEnumerable.GetEnumerator()
417 {
418 for (int index = 0; index < this.count; index++)
419 {
420 yield return this.items[index];
421 }
422 }
423
424 #endregion
425
426 #region 輔助方法
427
428 /// <summary>
429 /// 確保當前集合的容量,不小於指定的值。
430 /// </summary>
431 /// <param name="min">指定一個值,此方法會確保當前集合的容量不小於此值。</param>
432 private void EnsureCapacity(int min)
433 {
434 if (this.items.Length < min)
435 {
436 int num = this.items.Length;
437 if (num < min)
438 {
439 num = min;
440 }
441 this.Capacity = num;
442 }
443 }
444 #endregion
445 }
446 }
View Code