索引器必须是实例成员,不能声明为static;其get/set访问器需显式声明索引参数,支持重载但禁止自动实现;核心用途是让对象安全地模拟集合访问语义。

索引器必须是实例成员,不能声明为 static
这是最常被忽略的硬性限制:哪怕你只想封装一个静态字典,static indexer 也是非法的。编译器会直接报错 CS0708: 'xxx' cannot be declared static。想实现类似效果?只能用静态方法(如 GetItem(int key))或暴露静态属性(如 public static Dictionary),但这就失去了 obj[5] 的语法糖优势。
索引器的 get/set 访问器带参数,value 不是唯一隐式参数
属性的 get 没参数,set 只有隐式 value;而索引器的 get 和 set 都必须显式声明形参列表,且 set 的参数列表 = 索引参数 + 隐式 value。比如二维访问:
public string this[int row, int col]漏写任一索引参数,编译就失败。
{
get => _data[row, col];
set => _data[row, col] = value; // value 是 string,row/col 是索引参数
}
索引器支持重载,但不能自动实现
你可以同时定义 this[int i]、this[string key]、this[DateTime when],只要参数签名不同即可。但注意:public string this[int i] { get; set; } 这种自动实现写法是**不合法的**——编译器无法推断底层存储结构。你必须手动实现 get 和 set,并明确操作哪个字段(如 _list[i] 或 _dict[key])。否则会收到 CS0720: 'xxx': cannot declare a static indexer 类似误导性错误(实际是因自动实现被禁用)。
索引器真正的用途:让对象“长得像集合”,而非替代属性
它不是为了炫技,而是解决特定封装场景:
- 当你有一个内部
List或Dictionary,又不想暴露整个集合(防止外部误清空或修改引用) - 需要对访问做统一校验(如索引越界抛
ArgumentOutOfRangeException,键不存在时返回默认值或抛异常) - 想模拟多维语义(如矩阵类
matrix[2,3]、日志类logs["2026-01-30"][15])
GetAt(int) / SetAt(int, T) 方法更自然,也比公开属性更安全。
最容易被忽略的一点:索引器在序列化(如 JSON.NET)、反射遍历、WPF 绑定时默认不可见——它不会被当成普通属性处理。如果你依赖这些机制,得额外加 [IndexerName("Item")] 或改用显式方法。









