一、索引器 核心概念
1. 什么是索引器
默认情况下,自定义类的对象不能通过 索引 访问(只有数组、List 可以)。
索引器作用 :给自定义类添加 this[参数] 特殊属性,让对象支持 对象索引/参数 的方式取值、赋值。
本质:带参数的特殊属性,专门用来简化对象内部集合的访问。
2. 索引器固定语法
cs
// 访问修饰符 返回值 this[参数]
public 返回值 this[参数类型 参数名]
{
get { 取值逻辑 }
set { 赋值逻辑,value 为传入的值 }
}
3. 核心特点
-
使用 this 关键字定义
-
支持 get、set 访问器(可读可写/只读均可)
-
支持重载(多个不同参数的索引器)
-
只能定义在类、结构体中
二、基础索引器:数字索引(int 参数)
业务场景
ClassRoom 班级内部封装学生集合,通过索引器实现 room[0] 直接获取/修改学生对象。
完整核心代码
cs
class ClassRoom
{
// 内部封装学生集合
public List<Student> list = new List<Student>();
// 添加学生方法
public void Add(Student stu)
{
list.Add(stu);
}
// 数字索引器:通过下标 增改查
public Student this[int index]
{
get
{
// 根据索引返回对应学生对象
return list[index];
}
set
{
// 根据索引修改集合中的元素
list[index] = value;
}
}
}
调用方式
cs
// 完整调用测试代码
ClassRoom room = new ClassRoom();
// 添加两名学生
room.Add(new Student() { Name = "张三", Age = 10 });
room.Add(new Student() { Name = "李四", Age = 20 });
// 索引器set赋值:修改下标0的学生对象
room[0] = new Student() { Name = "王五", Age = 30 };
// 索引器get取值:读取下标0、1的学生信息
Console.WriteLine(room[0].Name + room[0].Age); // 输出:王五30
Console.WriteLine(room[1].Name + room[1].Age); // 输出:李四20
三、索引器重载(重点考点)
索引器支持参数类型不同实现重载,一个类可以定义多个索引器!
1. 字符串索引器(按姓名查询对象)
功能:通过 room["李四"] 根据姓名匹配并返回学生对象
cs
public Student this[string v]
{
get
{
// 模糊匹配姓名,返回对应学生对象
return list.Find(v1 => v1.Name == v);
}
}
完整调用测试(字符串索引器查询学生年龄):
cs
// 根据姓名查询李四、王五的年龄
Console.WriteLine(room["李四"].Age); // 输出:20
Console.WriteLine(room["王五"].Age); // 输出:30
2. 对象参数索引器(根据学生对象查索引下标)
功能:通过传入学生对象,匹配姓名,返回该学生在集合中的索引位置
cs
public int this[Student s1]
{
get
{
// 根据对象姓名匹配,返回索引值
int index = list.FindIndex(v => v.Name.Equals(s1.Name));
return index;
}
}
完整调用测试(对象索引器查询对应下标):
cs
// 传入学生对象,获取该学生在集合中的索引位置
int index1 = room[new Student() { Name = "李四", Age = 20 }];
int index2 = room[new Student() { Name = "王五", Age = 30 }];
Console.WriteLine(index1); // 输出:1
Console.WriteLine(index2); // 输出:0
索引器重载总结
同一个类中三个索引器,参数不同、功能不同,合法重载:
-
this[int index]:下标查对象、改对象 -
this[string name]:姓名查对象 -
this[Student stu]:对象查下标
四、进阶索引器:动态数组扩容索引器(实战练习)
业务需求
封装 string 数组,自定义索引器:索引超出数组长度时,自动扩容数组并赋值,突破普通数组固定长度限制。
完整核心代码
cs
public class Student
{
private string[] names = new string[4];
// 只读属性,默认返回第一个元素
public string Name { get => names[0]; }
// 构造函数初始化数组
public Student(string[] s)
{
names = s;
}
// 自定义索引器:支持自动扩容
public string this[int index]
{
get
{
// 根据索引取值
return names[index];
}
set
{
// 判断索引是否超出数组长度
if (index >= names.Length)
{
// 1. 创建长度+1的新数组
string[] newArr = new string[names.Length + 1];
// 2. 拷贝原数组数据到新数组
Array.Copy(names, newArr, names.Length);
// 3. 给新索引位置赋值
newArr[index] = value;
// 4. 替换原数组,完成扩容
names = newArr;
}
else
{
// 索引合法,直接赋值
names[index] = value;
}
}
}
}
完整调用测试
cs
// 动态扩容索引器 完整调用代码
// 初始化数组数据
Student stu = new Student(new string[] { "六一", "高考", "中考", "端午" });
// 读取默认第一个元素
Console.WriteLine(stu.Name); // 输出:六一
// 修改原有下标数据
stu[0] = "期末";
Console.WriteLine(stu[0]); // 输出:期末
Console.WriteLine(stu[1]); // 输出:高考
Console.WriteLine(stu[2]); // 输出:中考
Console.WriteLine(stu[3]); // 输出:端午
// 超出原数组长度,自动扩容赋值
stu[4] = "12";
Console.WriteLine(stu[4]); // 输出:12
扩容逻辑解析
-
初始数组长度固定为4
-
当执行
stu[4] = "12"时,索引超出范围 -
自动新建更长数组、拷贝原数据、赋值新元素、替换原数组
-
实现伪动态数组效果
五、索引器必考知识点 & 易错点
-
索引器必须用 this 定义,无方法名
-
索引器本质是带参数的属性,不是方法
-
支持重载:参数个数、类型不同即可重载
-
可以只写 get(只读索引器),不能只写 set
-
普通类、结构体可以写索引器,静态类不能定义索引器
-
value 关键字:固定接收索引器赋值时右侧的值
六、满分背诵口诀
-
索引器用this,对象括号能取值
-
本质属性带参数,get取值set赋值
-
参数不同可重载,数字字符对象皆可传
-
数组固定会越界,自定义索引可扩容