C# 索引器,实现IEnumerable接口的GetEnumerator()方法
当自定义类需要实现索引时,可以在类中实现索引器。
用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()方法的更多相关文章
- IEnumerable接口的扩展方法
/// <summary>/// IEnumerable接口的扩展方法,支持它的实现类是List的情况/// </summary>using System.Collection ...
- 实现了IEnumerable接口的GetEnumerator 即可使用 Foreach遍历,返回一个IEnumerator对象
#region 程序集 mscorlib.dll, v4.0.0.0 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framewor ...
- IEnumerable接口的Aggregate方法
以前小猪为了累加一个集合中的类容通常会写出类似这样的C#代码: string result ="": foreach (var item in items) { result+=i ...
- 接口、索引器、Foreach的本质(学习笔记)
接口 什么是接口? 接口代表一种能力,和抽象类类似但比抽象类的抽象程度更高! 接口的定义: public interface IEat//定义一个接口 { void Eat(string food); ...
- C# 接口中的索引器
索引器可在 接口(C# 参考) 上声明.接口索引器的访问器与类索引器的访问器具有以下方面的不同: 接口访问器不使用修饰符. 接口访问器没有体. 因此,访问器的用途是指示索引器是读写.只读还是只写.以下 ...
- 《精通C#》索引器与重载操作符(11.1-11.2)
1.索引器方法结构大致为<modifier><return type> this [argument list],它可以在接口中定义: 在为接口声明索引器的时候,记住声明只是表 ...
- 描述一下C#中索引器的实现过程,是否只能根据数字进行索引?
不是.可以用任意类型. 索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了 ...
- IEnumerable 接口 实现foreach 遍历 实例
额 为啥写着东西? 有次面试去,因为用到的时候特别少 所以没记住, 这个单词 怎么写! 经典的面试题: 能用foreach遍历访问的对象的要求? 答: 该类实现IEnumetable 接口 声明 ...
- C# 索引器简介
索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,是程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了数组和集合成员时,索引器 ...
随机推荐
- Java 线程
线程:线程是进程的组成部分,一个进程可以拥有多个线程,而一个线程必须拥有一个父进程.线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不能拥有系统资源.它与父进程的其他线程共享该进程的所有资 ...
- C# 破解 Reflector8.5
一.分析 破解.net .dll,可以使用reflector,但官方提供的reflector是需要购买的,因此,破解reflector势在必行. 二.破解Reflector具体步骤 下面为详细的破解步 ...
- Kooboo CMS技术文档之五:站点配置管理
站点关系 管理站点间的关系,站点可以有子站点,子站点继承父站点的部分配置数据,同时子站点还可以根据需要,本地化由父站点继承而来的数据.通过继承和本地化,可以让子站点在用最小的改动代价,来完成一个与父站 ...
- Ubuntu 16.10 安装byzanz截取动态效果图工具
1.了解byzanz截取动态效果图工具 byzanz能制作文件小,清晰的GIF动态效果图,不足就是,目前只能通过输入命令方式来录制. byzanz主要的参数选项有: -d, --duration=SE ...
- Paypal开发中遇到请求被中止: 未能创建 SSL/TLS 安全通道及解决方案
最近在基于ASP.NET上开发了Paypal支付平台,在ASP.NET开发的过程中没有遇到这个问题,但是引用到MVC开发模式中的时候就出现了"未能创建 SSL/TLS 安全通道及解决方案&q ...
- javascript工厂模式和构造函数模式创建对象
一.工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程(本书后面还将讨论其他设计模式及其在JavaScript 中的实现).考虑到在ECMAScript 中无法创 ...
- warensoft unity3d 更新说明
warensoft unity3d 组件的Alpha版本已经发布了将近一年,很多网友发送了改进的Email,感谢大家的支持. Warensoft Unity3D组件将继续更新,将改进的功能如下: 1. ...
- Linux之搭建自己的根文件系统
Hi!大家好,我是CrazyCatJack.又和大家见面了.今天给大家带来的是构建Linux下的根文件系统.希望大家看过之后都能构建出符合自己需求的根文件系统^_^ 1.内容概述 1.构造过程 今天给 ...
- 缓存工具类CacheHelper
代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syst ...
- .NET面试题集锦②(Part 二)
一.前言部分 文中的问题及答案多收集整理自网络,不保证100%准确,还望斟酌采纳. 1.实现产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复. ]; ArrayList my ...