前言:索引器核心定义(必背)
普通自定义类的对象,默认无法通过 对象[索引] 方式访问数据。
索引器是以 this 关键字定义的特殊属性 ,作用:给自定义类拓展 对象[参数] 的访问方式,让对象像数组、List 一样支持索引读写。
索引器支持重载,可以根据 数字、字符串、对象 不同参数实现不同功能。
第一段:系统 List 自带索引器演示
代码
List<int> list1 = new List<int>();
list1.Add(1);
list1[0] = 100;
Console.WriteLine(list1[0]);
Console.WriteLine(list1.Find(v => v % 2 == 0));
逐行解析
List<int> list1 = new List<int>();
创建一个存储整数的泛型集合,List 内部自带官方索引器,支持下标访问。
list1.Add(1);
向集合添加第一个元素,此时下标 0 的值为 1。
list1[0] = 100;
调用 List 索引器的 set 访问器,修改下标 0 的元素,覆盖原值为 100。
Console.WriteLine(list1[0]);
调用 List 索引器的 get 访问器,读取下标 0 数据,输出:100。
list1.Find(v => v % 2 == 0)
Lambda 查询集合中第一个偶数,100 是偶数,输出 100。
第二段:自定义实体类 Student(基础模型)
代码
class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
知识点解析
-
标准实体类,用于封装学生数据:姓名、年龄。
-
无索引器、无自定义方法,仅作为数据载体。
-
后续班级集合 List<Student> 存储的就是该类的实例对象。
第三段:ClassRoom 班级类 功能需求
需求注释
//1班级类对象可以通过Add添加一个学生对象 封装Add方法实现添加学生的功能
//2需要通过 room[0]访问添加学生对象 定义这样的this[int index]属性
需求拆解
-
封装 Add 方法:对外提供学生添加入口,隐藏内部集合操作。
-
定义数字索引器:实现
room[下标]读写学生对象。 -
拓展重载索引器:按姓名查对象、按对象查下标。
第四段:ClassRoom 基础集合 + Add 方法
代码
class ClassRoom
{
public List<Student> list = new List<Student>();
public void Add( Student stu)
{
list.Add(stu);
}
知识点解析
public List<Student> list
定义集合容器,专门存储所有学生对象,是整个班级的数据核心。
Add(Student stu)封装方法
面向对象封装思想:外部不需要操作集合,只需要调用 Add 就能添加学生,降低使用难度。
第五段:数字索引器 thisint index(核心必学)
代码
public Student this[int index]
{
get
{
return list[index];
}
set
{
list[index] = value;
}
}
逐段详解
-
索引器固定格式:
返回值 this[参数类型 参数名] -
get 访问器:触发场景
room[0]读取数据
根据传入的 index 下标,返回集合中对应位置的学生对象。
- set 访问器:触发场景
room[0] = 新对象
value 代表等号右侧赋值的学生对象,直接覆盖集合原下标数据。
- 功能:可读可写,让自定义班级类拥有数组式访问能力。
第六段:字符串重载索引器 thisstring v
代码
public Student this[string v]
{
get
{
Console.WriteLine(v+"++++++++++");
return list.Find(v1 => v1.Name == v);
}
}
知识点解析
-
索引器重载规则:参数类型不同构成重载(int 索引器 VS string 索引器)。
-
仅存在 get 访问器:只读索引器,只能查询、不能赋值。
-
核心逻辑:使用 List.Find 方法,根据传入的姓名,匹配集合中对应学生并返回完整对象。
-
使用方式:
room["李四"]直接获取李四的学生对象。
第七段:对象重载索引器 thisStudent s1
代码
public int this[Student s1]
{
get
{
int i1 = list.FindIndex(v => v.Name.Equals(s1.Name));
return i1;
}
}
知识点解析
-
参数为 Student 对象,再次构成索引器重载。
-
功能:反向查询,传入学生对象,返回该学生在集合中的下标索引。
-
FindIndex:查询匹配元素的下标,匹配姓名一致即返回索引。 -
使用方式:
room[学生对象]获取下标数字。
第八段:Main 方法索引器实操调用解析
代码分段解析
ClassRoom room = new ClassRoom();
room.Add(new Student() { Name = "张三", Age = 10 });
room.Add(new Student() { Name = "李四", Age = 20 });
创建班级对象,添加两名学生,下标 0=张三、下标1=李四。
room[0] = new Student() { Name="王五",Age= 30 };
触发 int 索引器 set 方法,覆盖下标0,张三被替换为王五。
Console.WriteLine(room[0].Name + room[0].Age);
Console.WriteLine(room[1].Name + room[1].Age);
触发 int 索引器 get 方法,读取:王五30、李四20。
Console.WriteLine(room["李四"].Age);
Console.WriteLine(room["王五"].Age);
触发 string 索引器 get 方法,根据姓名查询对象并输出年龄。
Console.WriteLine(room[new Student() { Name="李四",Age=20}]);
触发 Student 对象索引器,返回李四对应的下标 1。
第九段:升级版 Student 类(数组动态扩容索引器)
完整代码
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)
{
string[] newArr = new string[names.Length+1];
Array.Copy(names, newArr,names.Length);
newArr[index] = value;
names = newArr;
}
else
{
names[index] = value;
}
}
}
}
逐段详解
private string[] names = new string[4];
定义固定长度为4的私有字符串数组,存储多组名称数据。
public string Name { get => names[0]; }
只读属性,固定返回数组第一个元素。
- 构造方法
Student(string[] s)
接收外部数组,给内部 names 数组初始化赋值。
索引器动态扩容核心逻辑
get 访问器:根据下标读取数组对应元素。
set 访问器核心(重难点):
① 判断 index >= names.Length:索引超出原数组范围,需要扩容;
② 创建长度+1的新数组;
③Array.Copy 将旧数组所有数据拷贝到新数组;
④ 给新索引位置赋值;
⑤ 用新数组覆盖旧数组,完成动态扩容。
⑥ 若索引未越界,直接原地修改数组值。
第十段:Student 扩容索引器调用测试解析
测试代码
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]);
运行逻辑
-
初始化数组4个元素,Name 属性输出第一个值:六一。
-
stu[0] = "期末":索引未越界,直接修改下标0数据。 -
依次读取 0、1、2、3 下标数据。
-
stu[4] = "12":原数组最大下标3,4越界,触发动态扩容,数组长度变为5,新增下标4并赋值。
终极考点总结(必背)
-
索引器本质:this 修饰的特殊属性,非方法。
-
索引器支持重载:int、string、对象 不同参数可共存。
-
有 get、set:可读可写;只有 get:只读。
-
普通数组固定长度,自定义索引器可手动实现动态扩容。
-
索引器作用:封装内部集合,对外提供简洁的下标访问方式,符合面向对象封装特性。