把对象当作数组一样使用索引
与程序语言的许多功能一样,索引的优点归结为让你的程序更为直观。索引器使得类的客户能够类似数组一样索引对象实例。
定义索引器
索引器通常也称为灵巧的数组。定义索引器与定义属性是相似的。然而存在两个地方的不同。第一,索引器需要一个索引参数。第二,因为类自身当作一个数组使用,所以this关键字表示索引器的名称。简单的索引器示例:

2
class MyClass3
{4
public object this [int idx]5
{6
get7
{8
// Return desired data.9
}10
set 11
{12
// Set desired data.13
}14
}15
}16

索引器范例
using System;2
using System.Collections;3

4
class MyListBox5
{6
protected ArrayList data = new ArrayList();7

8
public object this[int idx]9
{10
get11
{12
if (idx > -1 && idx < data.Count)13
{14
return (data[idx]);15
}16
else17
{18
throw new InvalidOperationException("[MyListBox.set_Item]" +19
" Index out of range");20
}21
}22
set23
{24
if (idx > -1 && idx < data.Count)25
{26
data[idx] = value;27
}28
else if (idx == data.Count)29
{30
data.Add(value);31
}32
else33
{34
throw new InvalidOperationException(35
"[MyListBox.get_Item] Index out of range");36
}37
}38
}39
}40

41
class IndexersApp42
{43
public static void Main()44
{45
MyListBox lbx = new MyListBox();46
lbx[0] = "foo";47
lbx[1] = "bar";48
lbx[2] = "baz";49
Console.WriteLine("{0} {1} {2}", 50
lbx[0], lbx[1], lbx[2]);51
}52
}53

注意这个范例,我检验了数据索引溢出的错误。这不能依赖索引器,因为这如我所提到的:索引器只是方便类的用户能把对象当作一个数组来使用,并且不提供数据的内部表示方式相关的操作。然而,当学习一种新的语言特性时,查看它的实际用途比只看它的语法更有效。因此,在索引器的get/set方法中,我对被传递和存储在类成员ArrayList中的数据进行验证。当被传递的数据无法验证时,在这种情况下我多半选择抛出异常。
深入索引器
当C#编译器发现一个索引器语法时,将自动定义一个命名为Item的属性及相关的get/set方法。
正如你所看到的,在ILDASM树视图最后的条目是Item。如果你双击这个条目,你将看到标准的.property指示符和get_Item和set_Item。如果你尝试在类内部定义get_Item或set_Item方法编译器将出错,因为这些名字与索引器的方法名冲突。在Main方法的MSIL中可以进一步确认:用户访问类的索引器是通过调用get_Item和set_item方法来实现的。
同样注意到set_Item方法把Object引用作为第二个参数。这种安排明显地允许为你选择的任何类型指定索引器-这也是单一基类层次的另外一个优点。
因为对于客户来说,索引器可以把类当作数组看待,因此可以使用foreach迭代索引器,如下代码所示:
lbx[0] = "foo";2
lbx[1] = "bar";3
lbx[2] = "baz";4

5
foreach (object obj in lbx)6
{7

8
}9

允许你完全把类当作数组看待,不是索引器的原意。无论如何,接口IEmumenterable和类IEnumerate的组合使类的用户能够枚举所定义的集合。
设计指导方针
与其他语言的任何功能一样,索引器有它的局限性(place)。索引器只用在像数组一样直观处理的情景中。当考虑怎样实现一些新的功能影响你的类的用户和思考指导方针,使用更多的具体术语将使你的类更容易使用。
本文资料来源于:《Inside C# Second Edition》中的“Treating Objects Like Arrays by Using Indexers”

浙公网安备 33010602011771号