为何C#的List<T>要实现IReadOnlyCollection<T>接口?
.NET 中“只读集合”与“不可变集合”的澄清
我查阅文档发现,.NET Framework 在v4.0到v4.5版本之间,List<T>开始实现IReadOnlyCollection<T>接口。该接口的描述是:
表示一个强类型的只读元素集合。
但List<T>的元素明明可以修改,这让我困惑——显然我误解了这里“只读集合”的含义,同时也需要区分ReadOnlyCollection<T>和后续引入的不可变列表类型的差异。
1. IReadOnlyCollection<T>的“只读”含义
IReadOnlyCollection<T>的“只读”是接口层面的访问限制:这个接口仅定义了读取集合的成员(比如Count属性、支持遍历的方法),没有暴露任何修改集合结构(添加、删除元素)的方法。
- 当你把
List<T>实例赋值给IReadOnlyCollection<T>类型的变量时,你只能通过这个变量读取集合,无法调用Add、Remove等修改方法;但如果持有原始的List<T>引用,依然可以修改集合。 - 简单说,它限制的是通过该接口的访问权限,而非集合本身的可变性。
2. ReadOnlyCollection<T>的特性
ReadOnlyCollection<T>是包装器层面的只读:它是一个包装了基础集合的容器,自身没有提供任何修改集合结构的方法。
只读集合只是一个带有防止修改集合的包装器的集合;因此,如果对基础集合进行更改,只读集合会反映这些更改。
- 你无法通过
ReadOnlyCollection<T>的实例直接添加、删除元素,但如果能拿到它包装的基础集合(比如List<T>),修改基础集合后,ReadOnlyCollection<T>的内容也会跟着变化。
3. 真正的不可变集合类型
后续.NET版本引入的不可变类型,才是完全不可变的集合:
IImmutableList<T>接口:定义了不可变列表的规范,在.NET 6中引入。ImmutableList<T>类:当你向它添加或移除项时,会创建一个包含修改后内容的新列表副本,原始列表保持完全不变。ImmutableArray<T>结构体:另一种不可变集合实现,相比ImmutableList<T>在某些场景下有更好的性能。
这些不可变类型的核心是:一旦创建,原始集合的任何部分都不会被修改,所有修改操作都返回新的集合实例。
内容的提问来源于stack exchange,提问作者alelom
相关产品推荐
相关产品推荐

