C#索引器

引入:经常见有这样的类:如aClass a = new Class();然后在程序里出现个a[i]="some string";感觉好奇怪:既然没有声明类数组却用[]索引,而且返回个string类型,

索引器概述:简单说来,所谓C#索引器就是一类特殊的属性,通过它们你就可以像引用数组一样引用自己的类。

索引器使得对象可按照与数组相似的方法进行索引。

get 访问器返回值。set 访问器分配值。

this 关键字用于定义索引器。

value 关键字用于定义由 set 索引器分配的值。

索引器不必根据整数值进行索引,由您决定如何定义特定的查找机制。

索引器可被重载。

索引器可以有多个形参,例如当访问二维数组时。

C#语言一个最令人感兴趣的地方就是类的索引器(indexer)。简单说来,所谓索引器就是一类特殊的属性,通过它们你就可以像引用数组一样引用自己的类。显然,这一功能在创建集合类的场合特别有用,而在其他某些情况下,比如处理大型文件或者抽象某些有限资源等,能让类具有类似数组的行为当然也是非常有用的。

 

和方法一样,索引器有5种存取保护级别,和4种继承行为修饰,以及外部索引器。这些行为同方法没有任何差别,这里不再赘述。唯一不同的是索引器不能为静态(static),这在对象引用的语义下很容易理解。值得注意的是在覆盖(override)实现索引器时,应该用base[E]来存取父类的索引器。

 

和属性的实现一样,索引器的数据类型同时为get语句块的返回类型和set语句块中value关键字的类型

索引器的参数列表也是值得注意的地方。“索引”的特征使得索引器必须具备至少一个参数,该参数位于this关键字之后的中括号内。索引器的参数也只能是传值类型,不可以有ref(引用)和out(输出)修饰。参数的数据类型可以是C#中的任何数据类型。C#根据不同的参数签名来进行索引器的多态辨析。中括号内的所有参数在get和set下都可以引用,而value关键字只能在set下作为传递参数。

索引器通常用于对象容器中为其内的对象提供友好的存取界面--这也是为什么C#将方法包装成索引器的原因所在。实际上,我们可以看到索引器在.NET Framework类库中有大量的应用。

 

属性和索引器

   属性和索引器之间的差别:

   类的每一个属性都必须拥有唯一的名称,而类里定义的每一个索引器都必须拥有唯一的签名(signature)或者参数列表(这样就可以实现索引器重载)。

   属性可以是static(静态的)而索引器则必须是实例成员。

   为索引器定义的访问函数可以访问传递给索引器的参数,而属性访问函数则没有参数。

 

要声明类或结构上的索引器,使用 this 关键字(与属性相似):

public int this[int index]    // Indexer declaration
{
    // get and set accessors
}
备注
索引器类型及其参数类型必须至少如同索引器本身一样是可访问的。有关可访问级别的更多信息,请参见访问修饰符
索引器的签名由其形参的数量和类型组成。它不包括索引器类型或形参名。如果在同一类中声明一个以上的索引器,则它们必须具有不同的签名。
索引器值不归类为变量;因此,不能将索引器值作为 refout 参数来传递。
要为索引器提供一个其他语言可以使用的名字,请使用声明中的 name 属性。例如:
[System.Runtime.CompilerServices.IndexerName("TheItem")]
public int this [int index]   // Indexer declaration
{
}
此索引器将具有名称 TheItem。不提供名称属性将生成 Item 默认名称。
 示例 1
下面的示例说明如何声明私有数组字段、arr 和索引器。使用索引器可直接访问实例 test[i]。另一种使用索引器的方法是将数组声明为 public 成员并直接访问它的成员 arr[i]。
C#
class IndexerClass
{
    privateint[] arr = newint[100];
    publicintthis[int index]   // Indexer declaration
    {
        get
        {
            // Check the index limits.
            if (index < 0 || index >= 100)
            {
                return 0;
            }
            else
            {
                return arr[index];
            }
        }
        set
        {
            if (!(index < 0 || index >= 100))
            {
                arr[index] = value;
            }
        }
    }
}
 
class MainClass
{
    staticvoid Main()
    {
        IndexerClass test = new IndexerClass();
        // Call the indexer to initialize the elements #3 and #5.
        test[3] = 256;
        test[5] = 1024;
        for (int i = 0; i <= 10; i++)
        {
            System.Console.WriteLine("Element #{0} = {1}", i, test[i]);
        }
    }
}
 输出
Element #0 = 0
Element #1 = 0
Element #2 = 0
Element #3 = 256
Element #4 = 0
Element #5 = 1024
Element #6 = 0
Element #7 = 0
Element #8 = 0
Element #9 = 0
Element #10 = 0
请注意,当计算索引器的访问时(例如,在 Console.Write 语句中),将调用 get 访问器。因此,如果 get 访问器不存在,将发生编译时错误。
 使用其他值进行索引
C# 并不将索引类型限制为整数。例如,对索引器使用字符串可能是有用的。通过搜索集合内的字符串并返回相应的值,可以实现此类的索引器。由于访问器可被重载,字符串和整数版本可以共存。
 示例 2
在此例中,声明了存储星期几的类。声明了一个 get 访问器,它接受字符串(天名称),并返回相应的整数。例如,星期日将返回 0,星期一将返回 1,等等。
C#
// Using a string as an indexer value
class DayCollection
{
    string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };
 
    // This method finds the day or returns -1
    privateint GetDay(string testDay)
    {
        int i = 0;
        foreach (string day in days)
        {
            if (day == testDay)
            {
                return i;
            }
            i++;
        }
        return -1;
    }
 
    // The get accessor returns an integer for a given string
    publicintthis[string day]
    {
        get
        {
            return (GetDay(day));
        }
    }
}
 
class Program
{
    staticvoid Main(string[] args)
    {
        DayCollection week = new DayCollection();
        System.Console.WriteLine(week["Fri"]);
        System.Console.WriteLine(week["Made-up Day"]);
    }
}
 输出
5
-1
 可靠编程
提高索引器的安全性和可靠性有两种主要的方法:
当设置并检索来自索引器访问的任何缓冲区或数组的值时,请始终确保您的代码执行范围和类型检查。
应当为 getset 访问器的可访问性设置尽可能多的限制。这一点对 set 访问器尤为重要。有关更多信息,请参见非对称访问器可访问性(C# 编程指南)
  (来源:msdn )
 

 

posted @ 2010-08-23 15:57  AnnieBy  阅读(540)  评论(0编辑  收藏  举报