C# 索引器,实现IEnumerable接口的GetEnumerator()方法
Posted 云栾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 /// cells 8 /// </summary> 9 private Cell[] _cells; 10 11 /// <summary> 12 /// 获取Row中的Cell数 13 /// </summary> 14 public int Length { get; private set; } 15 16 /// <summary> 17 /// 索引 18 /// </summary> 19 public Cell this[int column] 20 { 21 get 22 { 23 return this[column]; 24 } 25 } 26 /// <summary> 27 /// 行 28 /// </summary> 29 /// <param name="values"></param> 30 public Row(object[] values) 31 { 32 this.Length = values.Length; 33 this._cells = new Cell[this.Length]; 34 for (int i = 0; i < this.Length; i++) 35 { 36 _cells[i].Value = values[i]; 37 _cells[i].StringValue = Convert.ToString(values[i]); 38 } 39 } 40 /// <summary> 41 /// 行 42 /// </summary> 43 /// <param name="values"></param> 44 public Row(string[] values) 45 { 46 this.Length = values.Length; 47 this._cells = new Cell[this.Length]; 48 for (int i = 0; i < this.Length; i++) 49 { 50 _cells[i].Value = values[i]; 51 _cells[i].StringValue = values[i]; 52 } 53 } 54 /// <summary> 55 /// 行 56 /// </summary> 57 /// <param name="values"></param> 58 public Row(int[] values) 59 { 60 this.Length = values.Length; 61 this._cells = new Cell[this.Length]; 62 for (int i = 0; i < this.Length; i++) 63 { 64 _cells[i].Value = values[i]; 65 _cells[i].StringValue = values[i].ToString(); 66 } 67 } 68 }
这时候,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 }
但是,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 >= 深入浅出-探究C#中的IEnumerableIEnumeratorYield