把对象当作数组一样使用索引

        与程序语言的许多功能一样,索引的优点归结为让你的程序更为直观。索引器使得类的客户能够类似数组一样索引对象实例。

定义索引器
       索引器通常也称为灵巧的数组。定义索引器与定义属性是相似的。然而存在两个地方的不同。第一,索引器需要一个索引参数。第二,因为类自身当作一个数组使用,所以this关键字表示索引器的名称。简单的索引器示例:

 1
 2  class MyClass
 3  {
 4      public object this [int idx]
 5      {
 6         get
 7         {
 8            // Return desired data.
 9         }

10         set 
11         {
12            // Set desired data.
13         }

14     }

15  }

16

索引器范例

 1using System;
 2using System.Collections;
 3
 4class MyListBox
 5{
 6    protected ArrayList data = new ArrayList();
 7
 8    public object this[int idx]
 9    {
10        get
11        {
12            if (idx > -1 && idx < data.Count)
13            {
14                return (data[idx]);
15            }

16            else
17            {
18                throw new InvalidOperationException("[MyListBox.set_Item]" +
19                    " Index out of range");
20            }

21        }

22        set
23        {
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            else
33            {
34                throw new InvalidOperationException(
35                    "[MyListBox.get_Item] Index out of range");
36            }

37        }

38    }

39}

40
41class IndexersApp
42{
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迭代索引器,如下代码所示:

1lbx[0= "foo";
2lbx[1= "bar";
3lbx[2= "baz";
4
5foreach (object obj in lbx)
6{
7   
8}

9

      允许你完全把类当作数组看待,不是索引器的原意。无论如何,接口IEmumenterable和类IEnumerate的组合使类的用户能够枚举所定义的集合。

设计指导方针
        与其他语言的任何功能一样,索引器有它的局限性(place)。索引器只用在像数组一样直观处理的情景中。当考虑怎样实现一些新的功能影响你的类的用户和思考指导方针,使用更多的具体术语将使你的类更容易使用。
  

本文资料来源于:《Inside C#  Second Edition》中的“Treating Objects Like Arrays by Using Indexers”

posted @ 2005-09-23 16:40  清香的工夫茶  阅读(1337)  评论(0编辑  收藏  举报