C# 索引器和属性的区别 C#索引器有什么特殊的用途

来源:这里教程网 时间:2026-02-21 17:41:57 作者:

索引器必须是实例成员,不能声明为 static

这是最常被忽略的硬性限制:哪怕你只想封装一个静态字典,

static indexer
也是非法的。编译器会直接报错
CS0708: 'xxx' cannot be declared static
。想实现类似效果?只能用静态方法(如
GetItem(int key)
)或暴露静态属性(如
public static Dictionary<int string> Items { get; }</int>
),但这就失去了
obj[5]
的语法糖优势。

索引器的 get/set 访问器带参数,value 不是唯一隐式参数

属性的

get
没参数,
set
只有隐式
value
;而索引器的
get
set
都必须显式声明形参列表,且
set
的参数列表 = 索引参数 + 隐式
value
。比如二维访问:
public string this[int row, int col]<br>{<br>    get => _data[row, col];<br>    set => _data[row, col] = value; // value 是 string,row/col 是索引参数<br>}
漏写任一索引参数,编译就失败。

索引器支持重载,但不能自动实现

你可以同时定义

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<t></t>
Dictionary<k></k>
,又不想暴露整个集合(防止外部误清空或修改引用)
需要对访问做统一校验(如索引越界抛
ArgumentOutOfRangeException
,键不存在时返回默认值或抛异常)
想模拟多维语义(如矩阵类
matrix[2,3]
、日志类
logs["2026-01-30"][15]
这时候,索引器比一堆
GetAt(int)
/
SetAt(int, T)
方法更自然,也比公开属性更安全。

最容易被忽略的一点:索引器在序列化(如 JSON.NET)、反射遍历、WPF 绑定时默认不可见——它不会被当成普通属性处理。如果你依赖这些机制,得额外加

[IndexerName("Item")]
或改用显式方法。

相关推荐