索引器(Indexer)是 C# 提供的一种特殊类成员,它可以让对象像数组一样使用下标访问数据。掌握索引器能够显著提升代码的可读性和可维护性,尤其适用于自定义集合类、矩阵类、缓存系统、棋盘游戏、学生成绩管理等场景。
本文将从基础概念、语法、进阶应用、实战案例、性能优化、设计思路、最佳实践全方位解析 C# 索引器,让你彻底掌握这一核心技能。
一、索引器基础概念
索引器本质上是"带参数的属性",通过 this 关键字声明,并可以实现 get 和 set 访问器。
特点
- 支持数组式访问:
obj[index] - 支持参数和重载,可使用 int、string、枚举等类型
- 可读可写,也可只读或只写
- 封装内部数据,保证安全性
基本语法
csharp
element-type this[int index]
{
get { return ...; }
set { ... = value; }
}
二、一维索引器基础示例
csharp
class NamesCollection
{
private string[] names = new string[5];
public string this[int index]
{
get => (index >= 0 && index < names.Length) ? names[index] : null;
set
{
if(index >= 0 && index < names.Length)
names[index] = value;
}
}
}
var nc = new NamesCollection();
nc[0] = "Alice";
nc[1] = "Bob";
nc[2] = "Charlie";
for(int i = 0; i < 5; i++)
Console.WriteLine(nc[i] ?? "Empty");
输出:
Alice
Bob
Charlie
Empty
Empty
一维索引器让对象行为类似数组,访问直观。
三、索引器重载:按索引和名称访问
csharp
class NamesCollection
{
private string[] names = new string[5];
public string this[int index]
{
get => names[index];
set => names[index] = value;
}
public int this[string name]
{
get
{
for(int i=0;i<names.Length;i++)
if(names[i]==name) return i;
return -1; // 未找到返回 -1
}
}
}
var nc = new NamesCollection();
nc[0]="Alice";
nc[1]="Bob";
nc[2]="Charlie";
Console.WriteLine(nc["Charlie"]); // 输出 2
设计思路与应用场景:
- 支持按索引或按名称访问,提高灵活性
- 适合姓名、商品名、字典类集合访问
- 可以扩展为按对象属性索引
四、二维索引器:矩阵访问示例
csharp
class Matrix
{
private int[,] data = new int[3,3];
public int this[int row,int col]
{
get => data[row,col];
set => data[row,col] = value;
}
}
var m = new Matrix();
m[0,1] = 10;
m[1,2] = 20;
Console.WriteLine(m[0,1]); // 10
Console.WriteLine(m[1,2]); // 20
应用场景:
- 矩阵运算
- 棋盘游戏
- 表格数据管理
优化提示:
- 可以加行列边界检查
- 对大矩阵可考虑稀疏矩阵优化
五、三维索引器:立体数据管理
csharp
class Cube
{
private int[,,] data = new int[3,3,3];
public int this[int x,int y,int z]
{
get => data[x,y,z];
set => data[x,y,z] = value;
}
}
var cube = new Cube();
cube[0,1,2] = 99;
Console.WriteLine(cube[0,1,2]); // 99
应用场景:
- 三维空间数据管理
- 3D 游戏地图
- 科学计算中的立体矩阵
六、只读/只写索引器
只读索引器:
csharp
class ReadOnlyCollection
{
private string[] items = {"A","B","C"};
public string this[int index] => items[index];
}
var roc = new ReadOnlyCollection();
Console.WriteLine(roc[1]); // B
只写索引器:
csharp
class WriteOnlyCollection
{
private string[] items = new string[3];
public string this[int index] { set { items[index] = value; } }
}
应用场景:
- 只读索引器:敏感数据或缓存
- 只写索引器:日志写入、队列入队
七、实战案例 1:学生成绩管理系统
csharp
class StudentGrades
{
private int[] grades = new int[5];
public int this[int index]
{
get => (index>=0 && index<grades.Length)?grades[index]:-1;
set
{
if(index>=0 && index<grades.Length && value>=0 && value<=100)
grades[index] = value;
}
}
public int Highest
{
get => grades.Max();
}
public int Lowest
{
get => grades.Min();
}
public double Average => grades.Average();
}
var sg = new StudentGrades();
sg[0]=90; sg[1]=85; sg[2]=78; sg[3]=92; sg[4]=88;
for(int i=0;i<5;i++)
Console.WriteLine($"第{i+1}门课: {sg[i]}");
Console.WriteLine($"最高分: {sg.Highest}");
Console.WriteLine($"最低分: {sg.Lowest}");
Console.WriteLine($"平均分: {sg.Average}");
优化与设计思路:
- 数据范围检查(0~100)
- 可以扩展为按科目名称索引
- 支持快速统计(最高、最低、平均)
八、实战案例 2:缓存管理系统
csharp
class Cache
{
private Dictionary<string,(string value, DateTime expiry)> data = new Dictionary<string,(string,DateTime)>();
public string this[string key]
{
get
{
if(data.ContainsKey(key))
{
var (val, expiry) = data[key];
if(DateTime.Now <= expiry) return val;
data.Remove(key); // 过期自动删除
}
return null;
}
set
{
data[key] = (value, DateTime.Now.AddMinutes(5)); // 默认5分钟过期
}
}
}
var cache = new Cache();
cache["user1"]="Alice";
Console.WriteLine(cache["user1"]); // Alice
真实缓存系统示例,带过期机制,展示索引器在实际开发中的应用。
九、实战案例 3:棋盘游戏索引器
csharp
class ChessBoard
{
private char[,] board = new char[8,8];
public char this[int row,int col]
{
get => board[row,col];
set
{
if(row>=0 && row<8 && col>=0 && col<8)
board[row,col] = value;
}
}
}
var chess = new ChessBoard();
chess[0,0]='R'; chess[0,1]='N';
Console.WriteLine(chess[0,0]); // R
Console.WriteLine(chess[0,1]); // N
场景扩展:
- 可以加入棋子移动方法
- 加入规则检查
- 可扩展到国际象棋或围棋棋盘类
十、高级索引器:枚举类型
csharp
enum Day { Mon, Tue, Wed, Thu, Fri }
class Schedule
{
private string[] tasks = new string[5];
public string this[Day day]
{
get => tasks[(int)day];
set => tasks[(int)day] = value;
}
}
var sched = new Schedule();
sched[Day.Mon]="Meeting";
Console.WriteLine(sched[Day.Mon]); // Meeting
枚举索引器便于语义化访问,比整数索引更直观。
十一、索引器性能优化
技巧
- 懒加载 :
get内部延迟创建对象 - 缓存机制:减少重复计算
- 边界检查:防止越界异常
- 只读索引器:降低写操作锁竞争
- 多线程安全 :索引器内部可使用锁或
ConcurrentDictionary
十二、索引器设计最佳实践
- 尽量封装内部数据,不直接暴露数组
- 根据业务选择只读、只写或可读写
- 对多维数据,确保边界检查完整
- 索引器应保持"访问逻辑",不要做复杂业务
- 对复杂数据可支持多重索引(int+string+枚举)
十三、总结
C# 索引器是强大工具,可让对象像数组访问数据,支持:
- 一维/二维/三维索引
- 索引器重载(int、string、枚举)
- 只读/只写控制
- 实战场景:学生成绩管理、缓存系统、棋盘游戏、三维空间数据
掌握索引器,你的 C# 代码将更直观、更灵活、更高效。
这篇文章包含:
- 基础语法、概念讲解
- 丰富的一维、二维、三维、枚举索引器示例
- 实际开发场景案例
- 性能优化和高级用法
- 设计思路和最佳实践