索引器总结
一、索引器基础概念
索引器 是C#中的一种特殊成员,它允许对象像数组一样使用 [] 运算符来访问元素。
基本语法
csharp
public 返回类型 this[参数类型 参数名]
{
get { return 数据; } // 获取数据时执行
set { 数据 = value; } // 设置数据时执行,value是关键字
}
二、索引器的基本用法
1. 单参数索引器(最常用)
csharp
public class MyCollection
{
private List<string> items = new List<string>();
// 索引器:通过int索引访问
public string this[int index]
{
get => items[index];
set => items[index] = value;
}
}
// 使用
var collection = new MyCollection();
collection[0] = "第一项"; // 设置
string item = collection[0]; // 获取
2. 多参数索引器
csharp
public class Matrix
{
private int[,] data = new int[10, 10];
public int this[int row, int col]
{
get => data[row, col];
set => data[row, col] = value;
}
}
// 使用
var matrix = new Matrix();
matrix[2, 3] = 100;
int val = matrix[2, 3];
3. 字符串参数索引器
csharp
public class StudentCollection
{
private List<Student> students = new List<Student>();
// 通过名字查找学生
public Student this[string name]
{
get => students.Find(s => s.Name == name);
set
{
int index = students.FindIndex(s => s.Name == name);
if (index >= 0)
students[index] = value;
}
}
}
三、索引器重载
同一个类中可以定义多个索引器,只要参数类型或数量不同:
csharp
public class SmartCollection
{
private List<Student> students = new List<Student>();
// 重载1:通过索引访问
public Student this[int index]
{
get => students[index];
set => students[index] = value;
}
// 重载2:通过名字访问
public Student this[string name]
{
get => students.Find(s => s.Name == name);
set
{
int index = students.FindIndex(s => s.Name == name);
if (index >= 0) students[index] = value;
}
}
// 重载3:通过ID访问
public Student this[int id, string type] // type参数用于区分
{
get => students.Find(s => s.ID == id);
}
}
四、索引器与属性的区别
| 特性 | 索引器 | 属性 |
|---|---|---|
| 语法 | this[参数] |
自定义名称 |
| 参数 | 必须有(1个或多个) | 无参数 |
| 调用方式 | obj[索引] |
obj.PropertyName |
| 重载 | 可以(基于参数) | 不可以 |
| 用途 | 访问集合元素 | 访问对象状态 |
五、总结
索引器的核心价值:
-
提供直观的访问语法:让自定义类型拥有类似数组的访问方式
-
增强代码可读性 :
config["Key"]比config.GetValue("Key")更直观 -
支持多维度访问:可以定义多维或多参数的索引器
-
实现接口契约:实现集合接口时必需
使用原则:
-
索引器适合"元素访问"语义
-
保持索引器逻辑简单
-
重要操作使用命名方法更清晰
-
添加适当的边界检查和异常处理
索引器是C#中非常有用的特性,特别是在创建集合类、配置管理、数据访问层等场景中,能显著提升代码的易用性和表达力。
接口和抽象类的区别
/* 相同的:都不能实例化,
* 都可以让派生类的对象赋值给抽象类或者接口类型变量 A1 a1 = new A1(); IPeople i1 = new IPeople();
* 都得必须在子类实现
* 不同点:
1:抽象类可以包含普通方法和成员 也可以抽象成员和方法, 接口只能有未实行的成员和方法
2: 接口可以多继承 抽象类还是和普通类的一样的继承
3:抽象类在子类通过override进行实现 接口直接使用即可
4: 抽象类修饰符可以添加修饰符 ,接口里面不能添加修饰符
5: 抽象类可以定义字段 接口里面不能定义字段 例如字段:int age;
*/