索引器是编译器对get_item/set_item方法的语法糖,不实现接口;必须为public实例成员,支持单或多参数(接口仅限单参数),不可static,重写需override整个索引器声明。

自定义索引器不是语法糖,而是显式实现 IIndexable 接口——等等,C# 根本没有这个接口。索引器本质是编译器对特定命名方法(get_Item/set_Item)的语法糖,不实现任何接口,也不强制要求泛型约束。
索引器方法名和签名必须严格匹配编译器预期
编译器把 this[...] 翻译成两个实例方法:get_Item 和 set_Item(仅当有 set 访问器时)。它们必须是 public 实例成员,返回类型和参数类型需与索引器声明一致。
- 错误写法:
public string GetItem(int i)—— 名字不对,编译器完全忽略 - 正确写法:
public string this[int index] { get { ... } set { ... } }→ 编译后生成string get_Item(int)和void set_Item(int, string) - 参数可以是任意类型(不止
int),比如string、DateTime,甚至多个参数(需用 params 或元组,但多参数索引器无法被 C# 语法直接调用,仅能通过反射或 IL 调用)
索引器不能是 static,也不能是 virtual/override 的独立成员
索引器本身不能加 static 修饰符;若基类定义了索引器,子类要重写,必须用 override 修饰整个索引器声明,而不是只修饰 get/set 访问器。
- 错误:在派生类里单独写
public override string get_Item(int i)—— 编译失败,这不是合法的重写语法 - 正确:在子类中写
public override string this[int i] { get => base[i].ToUpper(); set => base[i] = value; } - 如果基类索引器没标记
virtual或abstract,子类无法重写,只能用new隐藏 —— 但这是危险操作,多态调用时不会走子类逻辑
多维索引器只能靠一维语法模拟,别信“C# 支持二维索引器”这种过时说法
C# 语言层面只允许一维索引器签名(即一个参数列表)。所谓“二维数组式访问”,比如 obj[1, 2],实际是编译器对带两个参数的 get_Item 方法的支持 —— 但该方法必须声明为 this[int, int] 形式,且仅适用于 class 或 struct,不适用于接口(接口索引器只能单参数)。
- 可行:
public string this[int x, int y] { get => data[x, y]; }→ 编译为string get_Item(int, int) - 不可行:在接口中写
string this[int x, int y] { get; }→ 编译错误,接口索引器参数列表长度必须为 1 - 注意:这种多参数索引器无法被 foreach 枚举,也不能用于 LINQ 查询表达式(如
from x in obj select x会失败)
最容易被忽略的是:索引器的 get/set 访问器可以有不同访问级别(比如 get 是 public,set 是 private),但一旦设为 private,外部就无法赋值;而如果整个索引器声明为 private,那它对外部代码完全不可见——哪怕你写了 this[i],编译器也只认得到当前类内部的调用上下文。










