为什么
List<T>
在.NET 4.5中实现IReadOnlyList<T>
?
List<T>
不是只读...
因为
List<T>
实现了所有必要的方法/属性/等。 (然后是一些)IReadOnlyList<T>
。界面是一份契约,上面写着“我可以做至少这些事情。”
的文档表示它代表元素的只读集合。IReadOnlyList<T>
没错。该接口中没有修改器方法。这就是只读的意思,对吗?
IReadOnlyList<T>
以“典型”(合同)方式使用,而不是作为 标记。
接口仅描述将要实现的功能。它没有描述不会实现的功能。因此,IReadOnlyList 是一个不正确的接口名称,因为它不能指示不写入写入功能。
描述了可以读取列表内容的方法/函数。该接口应该是 IReadableList 而不是 IReadOnlyList。
实现接口与“标记”它不同。
List<T>
还实现了 IEnumerable<T>
,但这并不意味着您只能简单地枚举它。
他们添加了用于 API 创建的只读接口,而不是让您可以用接口标记只读类型。当我只想知道集合中元素的数量而不枚举它时,它允许我使用
IReadOnlyCollection<T>
作为参数,或者当我需要通过索引引用集合中的元素时使用 IReadOnlyList<T>
。这对每个人都有好处——我可以具体说明我需要调用者提供什么,同时允许调用者使用他想要的任何集合类型,只要它满足我通过参数类型设置的最低标准即可。
所以我认为更困难的问题是,为什么不会你有
List<T>
实施IReadOnlyList<T>
?
它实现接口的事实并不意味着它是只读的。但因为它实现了接口,所以您现在可以将其传递给需要
IReadOnlyList<T>
的方法。所以看待它的方法是,它实现了只读列表接口......以及一些写入方法。
接口
IReadOnlyList
和 IReadOnlyCollection
有点令人困惑,因为它们并不意味着集合是只读的,只是支持读取访问。来自 MSDN 文档(向下滚动到备注)
列表元素的内容不保证是只读的。
更好的名称是
IReadable
,请参阅为什么泛型 ICollection
在 .NET 4.5 中不实现 IReadOnlyCollection
?。此外,这意味着 IList
应该继承 IReadOnlyList
,尽管它不是由于向后兼容性,请参阅 为什么 IList<T>
不继承 IReadOnlyList<T>
?。
IReadOnlyList 是“引用不变性”概念的替代品,该概念在 C++ 中存在,但在 C# 中没有。 C++ 等效项是:
void func(T const* t) {...}
或者完全等同,正如有些人喜欢的那样:
void func(const T* t) {...}
它表示函数 func 不会改变其参数 t 引用的对象(称为 t 的“所指对象”)。它没有说明任何其他代码是否会改变 t 的所指对象,甚至没有说明可以。
因此,C# 接口是编译器构造的替代品。为什么C#没有引用不变性的概念是一个历史问题:我认为这是一个错误,但现在修复它已经太晚了。我认为提供接口替代品很好。多年来我一直在使用与 IReadOnlyList<> 完全相同的接口,幸运的是有另一个名称 IConstList<>。我可以将 IConstList<> 替换为 IReadOnlyList<>。
运行 IReadOnlyList(Of T) 的代码调用实现该接口的对象通常运行相同的执行线程,这不是真的吗?这可以防止对象被自身更改,除非它运行在不同的执行线程上,但对于这种情况,我们有同步调用来解决这个问题。