索引器
1 概念
1.1 定义
索引器(Indexer) 允许一个对象可以像数组一样使用下标的方式来访问,可被视为一种智能数组,索引器封装一组值,使用索引器时,语法和使用数组完全相同,使用数组访问运算符 [ ] 来访问该类的的成员。
1.2 语法
element-type this[int index]
{
// get 访问器
get
{
// 返回 index 指定的值
}
// set 访问器
set
{
// 设置 index 指定的值
}
}
几个重点概念要注意区分:
- 字段
- 属性
- 访问器(set;get)
- 索引器
2 示例
使用索引器讲一个整数字段表示一个bool 集合。
2.1 类程序
public class BoolSet_32
{
// 整数第32位为符号位,不用作保存数据
public static int INT_SIZE = 31;
private int m_nValue;
public BoolSet_32(int nValue)
{
this.m_nValue = nValue;
}
public bool this [int nIndex]
{
get
{
CheckIndex(nIndex);
return (0 != ((1 << nIndex) & m_nValue));
}
set
{
CheckIndex(nIndex);
if (value)
{
m_nValue |= (1 << nIndex);
}
else
{
m_nValue &= (~(1 << nIndex));
}
}
}
private void CheckIndex(int nIndex)
{
if (nIndex < 0 || nIndex > INT_SIZE)
throw new ArgumentOutOfRangeException("Index out of range!");
}
}
2.2 测试程序
3 特点
3.1 索引器可以使用非数值下标
数组只能使用数值下标,而索引器可以使用非数值下标。
3.2 索引器可以重载(和方法相似)
索引器重载示例
public class IndexNames
{
public static int NAME_NUMBERS = 10;
private string[] m_arrNames = new string[NAME_NUMBERS];
public IndexNames()
{
for (int i = 0; i != NAME_NUMBERS; ++i)
m_arrNames[i] = $"ZhangSan_{i}";
}
public string this[int nIndex]
{
get
{
CheckIndex(nIndex);
return m_arrNames[nIndex];
}
set
{
CheckIndex(nIndex);
m_arrNames[nIndex] = value;
}
}
// 重载索引器
public int this[string strName]
{
get
{
for (int i = 0; i != NAME_NUMBERS; ++i)
{
if (m_arrNames[i] == strName)
return i;
}
return - 1;
}
}
private void CheckIndex(int nIndex)
{
if (nIndex < 0 || nIndex > NAME_NUMBERS)
throw new ArgumentOutOfRangeException("Index out of range!");
}
}
3.3 索引器不能作为 ref 或 out 参数使用
数组可以作为 ref 或 out 参数使用,而索引器则不行。
4 接口中使用索引器
代码示例
interface IRawInt
{
bool this[int nIndex] { get; set; }
}
class RawInt : IRawInt
{
private int m_nValue;
private bool[] m_arrBool = new bool[10];
// 也可以将索引器实现声明为虚方法
public /*virtual*/ bool this[int nIndex]
{
get => m_arrBool[nIndex];
set => m_arrBool[nIndex] = value;
}
}