首页 > 代码库 > C# 索引器,实现IEnumerable接口的GetEnumerator()方法
C# 索引器,实现IEnumerable接口的GetEnumerator()方法
当自定义类需要实现索引时,可以在类中实现索引器。
用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 }
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 =http://www.mamicode.com/ values[i]; 31 this[i].StringValue =http://www.mamicode.com/ 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 =http://www.mamicode.com/ values[i]; 44 this[i].StringValue =http://www.mamicode.com/ 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 =http://www.mamicode.com/ values[i]; 57 this[i].StringValue =http://www.mamicode.com/ values[i].ToString(); 58 } 59 } 60 }
这时候,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 = http://www.mamicode.com/"学号"; 9 } 10 } 11 }
但是,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 }
这样,在调用的时候就能使用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 =http://www.mamicode.com/= 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 }
C# 索引器,实现IEnumerable接口的GetEnumerator()方法
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。