索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写。
1、索引器的定义
C#中的类成员可以是任意类型,包括数组和集合。当一个类包含了数组和集合成员时,索引器将大大简化对数组或集合成员的存取操作。
定义索引器的方式与定义属性有些类似,其一般形式如下:
[修饰符] 数据类型 this[索引类型 index]
{
get{//获得属性的代码}
set{ //设置属性的代码}
}
修饰符包括 public,protected,private,internal,new,virtual,sealed,override, abstract,extern.
数据类型是表示将要存取的数组或集合元素的类型。
索引器类型表示该索引器使用哪一类型的索引来存取数组或集合元素,可以是整数,可以是字符串;this表示操作本对象的数组或集合成员,可以简单把它理解成索引器的名字,因此索引器不能具有用户定义的名称。 例如:
class Z
{
//可容纳100个整数的整数集
private long[] arr = new long[100];
//声明索引器
public long this[int index]
{
get
{ //检查索引范围
if (index < 0 || index >= 100)
{
return 0;
}
else
{
return arr[index];
}
}
set
{
if (!(index < 0 || index >= 100))
{
arr[index] = value;
}
}
}
2、索引器的使用
通过索引器可以存取类的实例的数组成员,操作方法和数组相似,一般形式如下:
对象名[索引]
其中索引的数据类型必须与索引器的索引类型相同。例如:
Z z=new z();
z[0]=100;
z[1]=101;
Console.WriteLine(z[0]);
表示先创建一个对象z,再通过索引来引用该对象中的数组元素。
3、接口中的索引器
在接口中也可以声明索引器,接口索引器与类索引器的区别有两个:一是接口索引器不使用修饰符;二是接口索引器只包含访问器get或set,没有实现语句。访问器的用途是指示索引器是可读写、只读还是只写的,如果是可读写的,访问器get或set均不能省略;如果只读的,省略set访问器;如果是只写的,省略get访问器。
例如:
public interface IAddress
{
string this[int index]{get;set;}
string Address{get;set;}
string Answer();
}
表示所声明的接口IAddress包含3个成员:一个索引器、一个属性和一个方法,其中,索引器是可读写的。
4、索引器与属性的比较
索引器与属性都是类的成员,语法上非常相似。索引器一般用在自定义的集合类中,通过使用索引器来操作集合对象就如同使用数组一样简单;而属性可用于任何自定义类,它增强了类的字段成员的灵活性。
索引器允许类或者结构的实例按照与数组相同的方式进行索引取值,索引器与属性类似,不同的是索引器的访问是带参的。
索引器和数组比较:
(1)索引器的索引值(Index)类型不受限制
(2)索引器允许重载
(3)索引器不是一个变量
索引器和属性的不同点
(1)属性以名称来标识,索引器以函数形式标识
(2)索引器可以被重载,属性不可以
(3)索引器不能声明为static,属性可以
一个简单的索引器例子:
using System;
using System.Collections;
public class IndexerClass
{
private string[] name = new string[2];
//索引器必须以this关键字定义,其实这个this就是类实例化之后的对象
public string this[int index]
{
//实现索引器的get方法
get
{
if (index < 2)
{
return name[index];
}
return null;
}
//实现索引器的set方法
set
{
if (index < 2)
{
name[index] = value;
}
}
}
}
public class Test
{
static void Main()
{
//索引器的使用
IndexerClass Indexer = new IndexerClass();
//“=”号右边对索引器赋值,其实就是调用其set方法
Indexer[0] = "张三";
Indexer[1] = "李四";
//输出索引器的值,其实就是调用其get方法
Console.WriteLine(Indexer[0]);
Console.WriteLine(Indexer[1]);
}
}
以字符串作为下标,对索引器进行存取:
public class IndexerClass
{
//用string作为索引器下标的时候,要用Hashtable
private Hashtable name = new Hashtable();
//索引器必须以this关键字定义,其实这个this就是类实例化之后的对象
public string this[string index]
{
get { return name[index].ToString();
set { name.Add(index, value); }
}
}
public class Test
{
static void Main()
{
IndexerClass Indexer = new IndexerClass();
Indexer["A0001"] = "张三";
Indexer["A0002"] = "李四";
Console.WriteLine(Indexer["A0001"]);
Console.WriteLine(Indexer["A0002"]);
}
}
索引器的重载:
public class IndexerClass
{
private Hashtable name = new Hashtable();
//1:通过key存取Values
public string this[int index]
{
get { return name[index].ToString(); }
set { name.Add(index, value); }
}
//2:通过Values存取key
public int this[string aName]
{
get
{
//Hashtable中实际存放的是DictionaryEntry(字典)类型,如果要遍历一个Hashtable,就需要使用到DictionaryEntry
foreach(DictionaryEntry d in name)
{
if (d.Value.ToString() == aName)
{
return Convert.ToInt32(d.Key);
}
}
return -1;
}
set
{
name.Add(value, aName);
}
}
}
public class Test
{
static void Main()
{
IndexerClass Indexer = new IndexerClass();
//第一种索引器的使用
Indexer[1] = "张三";//set访问器的使用
Indexer[2] = "李四";
Console.WriteLine("编号为1的名字:" + Indexer[1]);//get访问器的使用
Console.WriteLine("编号为2的名字:" + Indexer[2]);
Console.WriteLine();
//第二种索引器的使用
Console.WriteLine("张三的编号是:" + Indexer["张三"]);//get访问器的使用
Console.WriteLine("李四的编号是:" + Indexer["李四"]);
Indexer["王五"] = 3;//set访问器的使用
Console.WriteLine("王五的编号是:" + Indexer["王五"]);
}
}
多参索引器:
using System;
using System.Collections;
//入职信息类
public class EntrantInfo
{
//姓名、编号、部门
private string name;
private int number;
private string department;
public EntrantInfo()
{
}
public EntrantInfo(string name, int num, string department)
{
this.name = name;
this.number = num;
this.department = department;
}
public string Name
{
get { return name; }
set { name = value; }
}
public int Num
{
get { return number; }
set { number = value; }
}
public string Department
{
get { return department; }
set { department = value; }
}
}
//声明一个类EntrantInfo的索引器
public class IndexerForEntrantInfo
{
private ArrayList ArrLst;//用于存放EntrantInfo类
public IndexerForEntrantInfo()
{
ArrLst = new ArrayList();
}
//声明一个索引器:以名字和编号查找存取部门信息
public string this[string name, int num]
{
get
{
foreach (EntrantInfo en in ArrLst)
{
if (en.Name == name && en.Num == num)
{
return en.Department;
}
}
return null;
}
set
{
//new关键字:C#规定,实例化一个类或者调用类的构造函数时,必须使用new关键
ArrLst.Add(new EntrantInfo(name, num, value));
}
}
//声明一个索引器:以编号查找名字和部门
public ArrayList this[int num]
{
get
{
ArrayList temp = new ArrayList();
foreach (EntrantInfo en in ArrLst)
{
if (en.Num == num)
{
temp.Add(en);
}
}
return temp;
}
}
//还可以声明多个版本的索引器...
}
public class Test
{
static void Main()
{
IndexerForEntrantInfo Info = new IndexerForEntrantInfo();
//this[string name, int num]的使用
Info["张三", 101] = "人事部";
Info["李四", 102] = "行政部";
Console.WriteLine(Info["张三", 101]);
Console.WriteLine(Info["李四", 102]);
Console.WriteLine();
//this[int num]的使用
foreach (EntrantInfo en in Info[102])
{
Console.WriteLine(en.Name);
Console.WriteLine(en.Department);
}
}
}