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

用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. 理解CSS边框border

    前面的话   边框是CSS盒模型属性中默默无闻的一个普通属性,CSS3的到来,但得边框属性重新焕发了光彩.本文将详细介绍CSS边框 基础样式   边框是一条以空格分隔的集合样式,包括边框粗细(边框宽度 ...

  2. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  3. BootStrap_02之全局样式及组件

    1.BootStrap指定的四种屏幕尺寸: ①超大PC屏幕--lg(large):w>=1200px: ②中等PC屏幕--md(medium):1200px>w>=992px: ③P ...

  4. 自定义Inspector检视面板

    Unity中的Inspector面板可以显示的属性包括以下两类:(1)C#以及Unity提供的基础类型:(2)自定义类型,并使用[System.Serializable]关键字序列化,比如: [Sys ...

  5. Matlab数值计算示例: 牛顿插值法、LU分解法、拉格朗日插值法、牛顿插值法

    本文源于一次课题作业,部分自己写的,部分借用了网上的demo 牛顿迭代法(1) x=1:0.01:2; y=x.^3-x.^2+sin(x)-1; plot(x,y,'linewidth',2);gr ...

  6. 强强联合,Testin云测&云层天咨众测学院开课了!

    Testin&云层天咨众测学院开课了! 共享经济时代,测试如何赶上大潮,利用碎片时间给女票或者自己赚点化妆品钱?   2016年12月13日,Testin联手云层天咨带领大家一起推开众测的大门 ...

  7. C# 工厂模式+虚方法(接口、抽象方法)实现多态

    面向对象语言的三大特征之一就是多态,听起来多态比较抽象,简而言之就是同一行为针对不同对象得到不同的结果,同一对象,在不同的环境下得到不同的状态. 实例说明: 业务需求:实现一个打开文件的控制台程序的d ...

  8. CSS三个定位——常规、浮动、绝对定位

    .dage { width: 868px; background: #5B8C75; border: 10px solid #A08C5A; margin-top: -125px; margin-le ...

  9. ABP理论之CSRF

    返回总目录 本篇目录 介绍 ASP.NET MVC ASP.NET WEB API ASP.NET Core[以后补上] 客户端类库 内部原理 介绍 CSRF[Cross-Site Request F ...

  10. Quality 是什么?

    Quality 是什么? 通常,我们谈及 Quality(质量)时,最常见的问题就是:Quality 是什么? 有很多业界先驱和研究人员已经回答了这个问题,我在这里并不会再给出一个新的答案.在学习总结 ...