C# 深入理解类(索引器)

发布于:2025-05-26 ⋅ 阅读:(24) ⋅ 点赞:(0)

索引器

假设我们要定义一个类Employee,它带有3个string型字段(如图7-3所示),那么可以使
用字段的名称访问它们,如Main中的代码所示。

image
然而有的时候,如果能使用索引访问它们将会很方便,好像该实例是字段的数组一样。这正
是索引器能做的事。如果为类Employee写一个索引器,方法Main看起来就像图7-14中的代码那样。
请注意没有使用点运算符,相反,索引器使用索引运算符,它由一对方括号和中间的索引组成。

使用索引字段

什么是索引器

索引器是一组get和set访问器,与属性类似。图7-15展示了一个类的索引器的表现形式,
该类可以获取和设置string型值。

索引器的表现形式

索引器和属性

索引器和属性在很多方面是相似的。

  • 和属性一样,索引器不用分配内存来存储。

  • 索引器和属性都主要被用来访问其他数据成员,它们与这些成员关联,并为它们提供获
    取和设置访问。

    • 属性通常表示单个数据成员。
    • 索引器通常表示多个数据成员。

    说明 可以认为索引器是为类的多个数据成员提供get和set访问的属性。通过提供索引器,
    可以在许多可能的数据成员中进行选择。索引本身可以是任何类型,而不仅仅是数值
    类型。


关于索引器,还有一些注意事项如下。

  • 和属性一样,索引器可以只有一个访问器,也可以两个都有。
  • 索引器总是实例成员,因此不能被声明为static。
  • 和属性一样,实现get和set访问器的代码不一定要关联到某个字段或属性。这段代码可
    以做任何事情也可以什么都不做,只要get访问器返回某个指定类型的值即可。

声明索引器

声明索引器的语法如下所示。请注意以下几点。

  • 索引器没有名称。在名称的位置是关键字this.
  • 参数列表在方括号中间。
  • 参数列表中必须至少声明一个参数。

声明索引器类似于声明属性。图7-16阐明了它们在语法上的相似点和不同点。

比较索引器声明和属性声明

索引器的set访问器

当索引器被用于赋值时,set访问器被调用,并接受两项数据,如下;

  • 一个名为value的隐式参数,其中持有要保存的数据;
  • 一个或更多索引参数,表示数据应该保存到哪里。

image
在set访问器中的代码必须检查索引参数,以确定数据应该存往何处,然后保存它。
set访问器的语法和含义如图7-7所示。图的左边展示了访问器声明的实际语法。右边展刁.
了访问器的语义,如果它是以普通方法的语法书写的。右边的图例表明set访问器有如下语义。

  • 它的返回类型为void.
  • 它使用的参数列表和索引器声明中的相同。
  • 它有一个名为value的隐式参数,值参类型和索引器类型相同。

image

索引器的get访问器

当使用索引器获取值时,可以通过一个或多个索引参数调用get访问器。索引参数指示获取
哪个值。

image

get访问器方法体内的代码必须检查索引参数,确定它表示的是哪个字段,并返回该字段的值。
get访问器的语法和含义如图7-18所示。图的左边展示了访问器声明的实际语法。右边展示
了访问器的语义,如果它是以普通方法的语法书写的。get访问器有如下语义。

  • 它的参数列表和索引器声明中的相同。
  • 它返回与索引器类型相同的值。

get访问器声明的语法和含义

关于索引器的更多内容

和属性一样,不能显式调用get和set访问器。取而代之,当索引器用在表达式中取值时,
将自动调用get访问器。当使用赋值语句对索引器赋值时,将自动调用set访问器。
在“调用"索引器时,要在方括号中提供参数。

image

为Employee示例声明索引器

下面的代码为先前示例中的类Employee声明了一个索引器。

  • 索引器需要读写string类型的值,所以string必须声明为索引器的类型。它必须声明为
    public,以便从类的外部访问。
  • 3个字段被随意地索引为整数0~2,所以本例中方括号中间名为index的形参必须为int型。
  • 在set访问器方法体内,代码确定索引指的是哪个字段,并把隐式变量value的值赋给它。
    在get访问器方法体内,代码确定索引指的是哪个字段,并返回该字段的值。
class Employee
{
    public string LastName;    //调用字段0
    public string FirstName;   //调用字段1

    public string CityOfBirth;  //调用字段2

    public string this[int index]  //索引器声明
    {
        void setUp() {
            {
                switch(index)
                {
                    case 0:LastName=value;
                    break;
                    case 1:FirstName=value;
                    break;
                    case 2:CityOfBirth=value;
                    break;

                    default:
                        throw new ArgumentOutOfRangeException("Index");
                }
            }

            get                       //get访问器声明
            {
                switch(index)
                {
                    case 0:return LastName;
                    case 1:return FirstName;
                    case 2:return CityOfBirth;

                    default:
                        throw new ArgumentOutOfRangeException("index");
                }
            }
        }
    }
}

另一个索引器示例

下面的示例为类Class1的两个int字段设置索引。

class Class1
{
    int Temp0;   //私有字段
    int Temp1;   //私有字段
    public int this[int index]  //索引
    {
        get
        {
            return(0==index)    //返回Temp0或Temp1的值
                    ?Temp0
                    :Temp1;
        }

        set
        {
            if(0==index)
                Temp0=value;     //注意隐式变量"value"
            else
                Temp1=value;     //注意隐式变量"value"
        }
    }
}

class Example
{
    static void Main()
    {
        Class1 a=new Class1();

        Console.WriteLine("Values -- T0:{0}, T1:{1}",a[0],a[1]);
        a[0]=15;
        a[1]=20;
        Console.WriteLine($"Values -- T0:{a[0]},T1:{a[1]}");
    }
}

索引器重载

只要索引器的参数列表不同,类就可以有任意多个索引器。索引器类型不同是不够的。这叫
作索引器重载,因为所有的索引器都有相同的“名称”:this访问引用。

例如,下面的代码有3个索引器:两个string类型的和一个int类型的。两个string类型
的索引中,一个带一个int参数,另一个带两个int参数。

class MyClass
{
    public string this[int index]
    {
        get{...}
        set{...}
    }

    public string this[int index1,int index2]
    {
        get{...}
        set{...}
    }

    public int this[float index1]
    {
        get{...}
        set{...}
    }
    ...
}

说明 请记住,类中重载的索引器必须有不同的参数列表。


网站公告

今日签到

点亮在社区的每一天
去签到