当自定义类需要实现索引时,可以在类中实现索引器。

用Table作为例子,Table由多个Row组成,Row由多个Cell组成,

我们需要实现自定义的table[0],row[0]

索引器定义格式为

[修饰符] 数据类型 this[索引类型 index]

以下是代码

     /// <summary>
/// 单元格
/// </summary>
public class Cell
{
/// <summary>
/// Value
/// </summary>
public object Value { get; set; }
/// <summary>
/// StringValue
/// </summary>
public string StringValue { get; set; }
}
     /// <summary>
/// 行
/// </summary>
public class Row
{
/// <summary>
/// cells
/// </summary>
private Cell[] _cells; /// <summary>
/// 获取Row中的Cell数
/// </summary>
public int Length { get; private set; } /// <summary>
/// 索引
/// </summary>
public Cell this[int column]
{
get
{
return this[column];
}
}
/// <summary>
/// 行
/// </summary>
/// <param name="values"></param>
public Row(object[] values)
{
this.Length = values.Length;
this._cells = new Cell[this.Length];
for (int i = ; i < this.Length; i++)
{
_cells[i].Value = values[i];
_cells[i].StringValue = Convert.ToString(values[i]);
}
}
/// <summary>
/// 行
/// </summary>
/// <param name="values"></param>
public Row(string[] values)
{
this.Length = values.Length;
this._cells = new Cell[this.Length];
for (int i = ; i < this.Length; i++)
{
_cells[i].Value = values[i];
_cells[i].StringValue = values[i];
}
}
/// <summary>
/// 行
/// </summary>
/// <param name="values"></param>
public Row(int[] values)
{
this.Length = values.Length;
this._cells = new Cell[this.Length];
for (int i = ; i < this.Length; i++)
{
_cells[i].Value = values[i];
_cells[i].StringValue = values[i].ToString();
}
}
}

这时候,Row就可以有自己的索引了,调用如下

     public class Test
{
public Test()
{
Row row = new Row(new string[] { "姓名", "性别", "工号" });
if (row.Length > )
{
row[].StringValue = "学号";
}
}
}

但是,Row虽然作为一个Cell的集合,却不能使用foreach进行遍历。这时候我们需要让Row继承IEnumerable接口,并且实现IEnumerable接口的GetEnumerator()方法,

在public class Row : IEnumerable { }中添加如下代码:

         /// <summary>
/// 实现GetEnumerator()方法
/// </summary>
/// <returns></returns>
public IEnumerator GetEnumerator()
{
for (int i = ; i < this.Length; i++)
{
yield return this[i];
}
}

这样,在调用的时候就能使用foreach遍历了。
Table和Row的关系同理。

同样,我们还可以继承ICollection<T>, IEnumerable<T>, IList<T>等接口,实现相关接口的方法,就可以打造属于自己的集合了。

一个完整的Demo如下:

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text; namespace MyCollection
{
/// <summary>
/// 表示 Cell 集合
/// </summary>
[DebuggerDisplay("Count = {Count}")]
[Serializable]
public class MyCollection : IEnumerable, IEnumerable<Cell>, ICollection<Cell>, IList<Cell>
{
#region 字段 /// <summary>
/// 表示空的 Row 图层的数组。
/// </summary>
private readonly static Row[] emptyArray = null; /// <summary>
/// 存储 Row 图层的数组。
/// </summary>
private Row[] items = null; /// <summary>
/// 当前 Row 图层的集合的元素数。
/// </summary>
private int count = ; #endregion #region 属性 /// <summary>
/// 获取或设置该 Row 的元素总数。
/// </summary>
/// <exception cref="System.ArgumentOutOfRangeException">MyCollection.Capacity 设置为小于 MyCollection.Count 的值。</exception>
private int Capacity
{
get
{
return this.items.Length;
}
set
{
if (value != this.items.Length)
{
if (value < this.count)
{
throw new ArgumentOutOfRangeException("Capacity", "MyCollection.Capacity 设置为小于 MyCollection.Count 的值。");
}
if (value > )
{
Row[] destArray = new Row[value];
if (this.count > )
{
Array.Copy(this.items, , destArray, , this.count);
}
this.items = destArray;
}
else
{
this.items = emptyArray;
}
}
}
} #endregion #region 构造函数
/// <summary>
/// 对 LayerCollection 类进行初始化。
/// </summary>
static MyCollection()
{
emptyArray = new Row[];
} /// <summary>
/// 初始化 HuaXing.ExamOperation.SimulateFlash.LayerCollection 类的新实例。<para/>
/// 表示 Layer 图层的集合。
/// </summary>
public MyCollection()
{
this.items = emptyArray;
}
#endregion #region IList<Row> 成员 #region IndexOf /// <summary>
/// 搜索指定的 Row 对象,并返回整个 MyCollection 中第一个匹配项的从零开始的索引。
/// </summary>
/// <param name="item">要在 MyCollection 中定位的 Row 对象。</param>
/// <returns>如果在 MyCollection 中找到 item 的第一个匹配项,则为该项的从零开始的索引;否则为-1。</returns>
public int IndexOf(Row item)
{
return Array.IndexOf<Row>(this.items, item, , this.count);
} /// <summary>
/// 搜索指定的 Row 对象,并返回整个 MyCollection 中从指定索引到最后一个元素的元素范围内第一个匹配项的从零开始的索引。
/// </summary>
/// <param name="item">要在 MyCollection 中定位的 Row 对象。</param>
/// <param name="index">从零开始的搜索的起始索引。</param>
/// <returns>如果在 MyCollection 中从 index 到最后一个元素的元素范围内找到 item 的第一个匹配项,则为该项的从零开始的索引;否则为-1。</returns>
/// <exception cref="System.ArgumentOutOfRangeException">index 不在 MyCollection 的有效索引范围内。</exception>
public int IndexOf(Row item, int index)
{
if (index < || index > this.count)
{
throw new ArgumentOutOfRangeException("index", "index 不在 MyCollection 的有效索引范围内。");
}
return Array.IndexOf<Row>(this.items, item, index, this.count - index);
} /// <summary>
/// 搜索指定的 Row 对象,并返回整个 MyCollection 中从指定的索引开始并包含指定的元素数的元素范围内第一个匹配项的从零开始的索引。
/// </summary>
/// <param name="item">要在 MyCollection 中定位的 Row 对象。</param>
/// <param name="index">从零开始的搜索的起始索引。</param>
/// <param name="count">要搜索的部分中的元素数。</param>
/// <returns>如果在 MyCollection 中从 index 开始并包含 count 个元素的元素范围内找到 item 的第一个匹配项,则为该项的从零开始的索引;否则为-1。</returns>
/// <exception cref="System.ArgumentOutOfRangeException">index 不在 MyCollection 的有效索引范围内 或 count 小于 0 或 index 和 count 未指定 MyCollection 中的有效部分。</exception>
public int IndexOf(Row item, int index, int count)
{
if (index < || index > this.count)
{
throw new ArgumentOutOfRangeException("index", "index 不在 MyCollection 的有效索引范围内。");
}
if ((count < ) || (index > (this.count - count)))
{
throw new ArgumentOutOfRangeException("count", "count 小于 0 或 index 和 count 未指定 MyCollection 中的有效部分。");
}
return Array.IndexOf<Row>(this.items, item, index, count);
} #endregion #region Insert /// <summary>
/// 将 Row 对象插入 MyCollection 的指定索引处。
/// </summary>
/// <param name="index">从零开始的索引,应在该位置插入 item。</param>
/// <param name="item">要插入的 Row 对象。</param>
/// <exception cref="System.ArgumentOutOfRangeException">index 小于 0 或 index 大于 MyCollection.Count。</exception>
public void Insert(int index, Row item)
{
if (index < || index > this.count)
{
throw new ArgumentOutOfRangeException("index", "index 小于 0 或 index 大于 MyCollection.Count。");
}
if (this.count == this.items.Length)
{
this.EnsureCapacity(this.count + );
}
if (index < this.count)
{
Array.Copy(this.items, index, this.items, index + , this.count - index);
}
this.items[index] = item;
this.count++;
} #endregion #region RemoveAt /// <summary>
/// 移除 MyCollection 的指定索引处的 Row 对象。
/// </summary>
/// <param name="index">要移除的 Row 对象的从零开始的索引。</param>
/// <exception cref="System.ArgumentOutOfRangeException">index 小于 0 或 index 等于或大于 MyCollection.Count。</exception>
public void RemoveAt(int index)
{
if (index < || index >= this.count)
{
throw new ArgumentOutOfRangeException("index", "index 小于 0 或 index 等于或大于 MyCollection.Count。");
}
this.count--;
if (index < this.count)
{
Array.Copy(this.items, index + , this.items, index, this.count - index);
}
this.items[this.count] = default(Row);
} #endregion #region Item[Int32] /// <summary>
/// 获取或设置指定索引处的 Row 对象。
/// </summary>
/// <param name="index">要获取或设置的 Row 对象从零开始的索引。</param>
/// <returns>指定索引处的 Row 对象。</returns>
/// <exception cref="System.ArgumentOutOfRangeException">index 小于 0 或 index 等于或大于 MyCollection.Count。</exception>
public Row this[int index]
{
get
{
if (index < && index >= this.count)
{
throw new ArgumentOutOfRangeException("index", "index 小于 0 或 index 等于或大于 MyCollection.Count。");
}
else
{
return this.items[index];
}
}
set
{
if (index < && index >= this.count)
{
throw new ArgumentOutOfRangeException("index", "index 小于 0 或 index 等于或大于 MyCollection.Count。");
}
else
{
this.items[index] = value;
}
}
} #endregion #endregion #region ICollection<Row> 成员 #region Add /// <summary>
/// 将 Row 对象,添加到 MyCollection 的结尾处。
/// </summary>
/// <param name="item">要添加到 MyCollection 的末尾处的 Row 对象。</param>
public void Add(Row item)
{
if (this.count == this.items.Length)
{
this.EnsureCapacity(this.count + );
}
this.items[this.count++] = item;
} #endregion #region Clear /// <summary>
/// 从 MyCollection 集合中移除所有元素。
/// </summary>
public void Clear()
{
if (this.count > )
{
Array.Clear(this.items, , this.count);
this.count = ;
}
} #endregion #region Contains /// <summary>
/// 确定 MyCollection 集合中,是否包含特定值。
/// </summary>
/// <param name="value">要在 MyCollection 集合中查找的 Row。</param>
/// <returns>如果在 MyCollection 集合中找到 Row,则为true;否则为false。</returns>
public bool Contains(Row value)
{
if (value == null)
{
for (int j = ; j < this.count; j++)
{
if (this.items[j] == null)
{
return true;
}
}
return false;
}
EqualityComparer<Row> comparer = EqualityComparer<Row>.Default;
for (int i = ; i < this.count; i++)
{
if (comparer.Equals(this.items[i], value))
{
return true;
}
}
return false;
} #endregion #region CopyTo /// <summary>
/// 将整个 MyCollection 复制到一维数组中,从目标数组的开头开始放置。
/// </summary>
/// <param name="array">作为从 MyCollection 复制的元素的目标位置的一维数组。</param>
/// <exception cref="System.ArgumentException">源 MyCollection 中的元素数大于目标 array 可包含的元素数。</exception>
/// <exception cref="System.ArgumentNullException">array 为 null。</exception>
public void CopyTo(Row[] array)
{
this.CopyTo(array, );
} /// <summary>
/// 将整个 MyCollection 复制到一维数组中,从目标数组的指定索引位置开始放置。
/// </summary>
/// <param name="array">作为从 MyCollection 复制的元素的目标位置的一维数组。</param>
/// <param name="arrayIndex">array 中从零开始的索引,在此处开始复制。</param>
/// <exception cref="System.ArgumentException">arrayIndex 等于或大于 array 的长度 或 源 MyCollection 中的元素数目大于从 arrayIndex 到目标 array 末尾之间的可用空间。</exception>
/// <exception cref="System.ArgumentNullException">array 为 null。</exception>
/// <exception cref="System.ArgumentOutOfRangeException">arrayIndex 小于 0。</exception>
public void CopyTo(Row[] array, int arrayIndex)
{
Array.Copy(this.items, , array, arrayIndex, this.count);
} /// <summary>
/// 将一定范围的元素从 MyCollection 复制到一维数组中,从目标数组的指定索引位置开始放置。
/// </summary>
/// <param name="index">源 MyCollection 中复制开始位置的从零开始的索引。</param>
/// <param name="array">作为从 MyCollection 复制的元素的目标位置的一维数组。</param>
/// <param name="arrayIndex">array 中从零开始的索引,在此处开始复制。</param>
/// <param name="count">要复制的元素数。</param>
/// <exception cref="System.ArgumentException">index 等于或大于源 MyCollection 的 MyCollection.Count 或 arrayIndex 等于或大于 array 的长度 或 从 index 到源 MyCollection 的末尾的元素数大于从 arrayIndex 到目标 array 的末尾的可用空间。</exception>
/// <exception cref="System.ArgumentNullException">array 为 null。</exception>
/// <exception cref="System.ArgumentOutOfRangeException">index 小于 0 或 arrayIndex 小于 0 或 count 小于 0。</exception>
public void CopyTo(int index, Row[] array, int arrayIndex, int count)
{
if ((this.count - index) < count)
{
throw new ArgumentException("index 等于或大于源 MyCollection 的 MyCollection.Count 或 arrayIndex 等于或大于 array 的长度 或 从 index 到源 MyCollection 的末尾的元素数大于从 arrayIndex 到目标 array 的末尾的可用空间。", "index");
}
Array.Copy(this.items, index, array, arrayIndex, count);
} #endregion #region Count /// <summary>
/// 获取当前 Row 集合的元素数。
/// </summary>
public int Count
{
get
{
return this.count;
}
} #endregion #region IsReadOnly /// <summary>
/// 获取一个值,该值指示 MyCollection 是否为只读。
/// </summary>
bool ICollection<Row>.IsReadOnly
{
get
{
return false;
}
} #endregion #region Remove /// <summary>
/// 从 MyCollection 中移除特定 Row 对象的第一个匹配项。
/// </summary>
/// <param name="item">要从 MyCollection 中移除的 Row 对象。</param>
/// <returns>如果成功移除 item,则为 true;否则为 false。如果在 MyCollection 中没有找到 item,该方法也会返回 false。</returns>
public bool Remove(Row item)
{
int index = this.IndexOf(item);
if (index >= )
{
this.RemoveAt(index);
return true;
}
return false;
} #endregion #endregion #region IEnumerable<Row> 成员 public IEnumerator<Row> GetEnumerator()
{
for (int index = ; index < this.count; index++)
{
yield return this.items[index];
}
} #endregion #region IEnumerable 成员 IEnumerator IEnumerable.GetEnumerator()
{
for (int index = ; index < this.count; index++)
{
yield return this.items[index];
}
} #endregion #region 辅助方法 /// <summary>
/// 确保当前集合的容量,不小于指定的值。
/// </summary>
/// <param name="min">指定一个值,此方法会确保当前集合的容量不小于此值。</param>
private void EnsureCapacity(int min)
{
if (this.items.Length < min)
{
int num = this.items.Length;
if (num < min)
{
num = min;
}
this.Capacity = num;
}
}
#endregion
}
}

C# 索引器,实现IEnumerable接口的GetEnumerator()方法的更多相关文章

  1. IEnumerable接口的扩展方法

    /// <summary>/// IEnumerable接口的扩展方法,支持它的实现类是List的情况/// </summary>using System.Collection ...

  2. 实现了IEnumerable接口的GetEnumerator 即可使用 Foreach遍历,返回一个IEnumerator对象

    #region 程序集 mscorlib.dll, v4.0.0.0 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framewor ...

  3. IEnumerable接口的Aggregate方法

    以前小猪为了累加一个集合中的类容通常会写出类似这样的C#代码: string result ="": foreach (var item in items) { result+=i ...

  4. 接口、索引器、Foreach的本质(学习笔记)

    接口 什么是接口? 接口代表一种能力,和抽象类类似但比抽象类的抽象程度更高! 接口的定义: public interface IEat//定义一个接口 { void Eat(string food); ...

  5. C# 接口中的索引器

    索引器可在 接口(C# 参考) 上声明.接口索引器的访问器与类索引器的访问器具有以下方面的不同: 接口访问器不使用修饰符. 接口访问器没有体. 因此,访问器的用途是指示索引器是读写.只读还是只写.以下 ...

  6. 《精通C#》索引器与重载操作符(11.1-11.2)

    1.索引器方法结构大致为<modifier><return type> this [argument list],它可以在接口中定义: 在为接口声明索引器的时候,记住声明只是表 ...

  7. 描述一下C#中索引器的实现过程,是否只能根据数字进行索引?

    不是.可以用任意类型. 索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了 ...

  8. IEnumerable 接口 实现foreach 遍历 实例

    额 为啥写着东西? 有次面试去,因为用到的时候特别少 所以没记住, 这个单词 怎么写! 经典的面试题: 能用foreach遍历访问的对象的要求? 答:  该类实现IEnumetable 接口   声明 ...

  9. C# 索引器简介

    索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,是程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了数组和集合成员时,索引器 ...

随机推荐

  1. 12306官方火车票Api接口

    2017,现在已进入春运期间,真的是一票难求,深有体会.各种购票抢票软件应运而生,也有购买加速包提高抢票几率,可以理解为变相的黄牛.对于技术人员,虽然写一个抢票软件还是比较难的,但是还是简单看看123 ...

  2. 使用webstorm+webpack构建简单入门级“HelloWorld”的应用&&引用jquery来实现alert

    使用webstorm+webpack构建简单入门级"HelloWorld"的应用&&构建使用jquery来实现 1.首先你自己把webstorm安装完成. 请参考这 ...

  3. Yii1.1的验证规则

    在Yii1.1的数据验证是由CValidator完成,在CValidator中提供了各种基本的验证规则 <?php public static $builtInValidators=array( ...

  4. Dapper扩展之~~~Dapper.Contrib

    平台之大势何人能挡? 带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4822808.html#skill 上一篇文章:Dapper逆天入门~强类型,动态类型 ...

  5. 深入浅出JavaScript之原型链&继承

    Javascript语言的继承机制,它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instanc ...

  6. WPF CheckBox 样式

    <Style x:Key="FocusVisual"> <Setter Property="Control.Template"> < ...

  7. 利用poi导出Excel

    import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.r ...

  8. 分布式学习系列【dubbo入门实践】

    分布式学习系列[dubbo入门实践] dubbo架构 组成部分:provider,consumer,registry,monitor: provider,consumer注册,订阅类似于消息队列的注册 ...

  9. Eclipse使用Git教程

    A:点击Window--->Show view--->other..--->Git Repositories--->[OK] B:克隆码云上的代码仓库 C:选择对应目录存储你的 ...

  10. 树莓派3B的食用方法-1(装系统 网线ssh连接)

    首先要有一个树莓派3B , 在某宝买就行, 这东西基本上找到假货都难,另外国产和英国也没什么差别,差不多哪个便宜买哪个就行. 不要买店家的套餐,一个是配的东西有些不需要,有的质量也不好. 提示:除了G ...