所谓索引器(the Indexer)其实就是一种属性(Property)(具体来说是一种含参属性) (详见.NET框架 程序设计 p220)
也可以将它看作是对操作符 [ ] 的重载。
索引器的参数除了可以是Int之外,也可以是double 甚至是object。但只能有一个参数
具体参数类型要求如下:避免为索引器设置除 System.Int32、System.Int64、System.String、System.Object、枚举或泛型类型参数之外的其他参数类型。(摘自MSDN)
另:索引器支持重载。
看看平时最常用的String就大致可以明白索引器的实际作用了。String类型可以通过[n]来访问第n个索引的值(char)。省去了从String -> char[] 的过程。
String str = "Hello World";
//如果不用索引器,我们大概会这么做
char[] charArray = str.ToCharArray();
Console.WriteLine(charArray[1].ToString());//输出e
//有了索引器之后,方便多了,我们可以通过str[i]来直接访问对应的元素
Console.WriteLine(str[1].ToString());//输出e
索引器的声明模型如下
public T1 this[T2] //T1为返回值,T2为索引参数的类型
{
get{...}
set{...}
}
举个小例子如下:
public class TestIndexer
{
private DataTable table;
public TestIndexer()
{
//构建一张表
table = new DataTable();
table.Columns.Add("key",typeof(Int16));
table.Columns.Add("value",typeof(String));
table.Rows.Add("1", "Jan");
table.Rows.Add("2", "Feb");
}
public String this[Int16 index]//indexer 1(根据数字月份返回英文)
{
get
{
for (int i = 0; i < table.Rows.Count; i++ )
{
if ( (Int16)table.Rows[i]["key"] == index)
{
return table.Rows[i]["value"].ToString();
}
}
return "Null";
}
}
public String this[String season]//indexer 2(根据英文月份返回数字)
{
get
{
for (int i = 0; i < table.Rows.Count; i++)
{
if (table.Rows[i]["value"].ToString() == season)
{
return table.Rows[i]["key"].ToString();
}
}
return "Null";
}
}
public int this[Int32 i]//indexer 3(干扰器,干扰Indexer1)
{
get
{
return i;
}
}
}//class
void Main(string[] args)
{
TestIndexer t = new TestIndexer();
Console.WriteLine("t[1] = {0}", t[(Int16)1]);//调用1号索引器 输出 Jan(将1显式转换为Int16类型)
Console.WriteLine("t[\"Jan\"] = {0}", t["Jan"]);//调用2号索引器 输出1
Console.WriteLine("t[1] = {0}", t[1]);//调用3号索引器 输出 1(这个1直接被隐式转换成Int32,因此调用3号索引器)
}
后记:之前看书时对“索引器可以看做是对 [ ] 操作符的重载”有点不解,但博客写到这里又回头仔细地思考了一下算是明白了。
之前初看索引器的概念时觉得这东西好像很抽象很厉害,现在看来完全是纸老虎。
本质也就是个属性,如果不用索引器也可以改用方法(Method)来完成,例如上例中的几个索引器,可以直接用如下的方法替代:
public String getNameByValue(int i){}//代替索引器1
public String getValueByName(string v){}//代替索引器2
而且在本例中这种对方法的调用比 t [ ] 这种调用方式更具可读性。