2013-07-01 25 views
33

List<T>实现IReadOnlyCollection<T>接口并提供AsReadOnly()方法,它返回ReadOnlyCollection<T>(这又实现IReadOnlyCollection<T>)。列表<T> .AsReadOnly()与IReadOnlyCollection <T>

AsReadyOnly()的用法和原因是什么?它存在一种或两种边缘情况的气味,其中仅返回列表IReadOnlyCollection<T>就不够好。

起初我虽然可能是为了防止铸造成本,但看起来你可以用ReadOnlyCollection<T>Items访问器来做到这一点。

顺便说一句。 ReadOnlyCollection<T>类型的文档显示为

为通用只读集合提供基类。

,在我的头,具有描述为

构造冲突初始化(...)类,它是围绕指定列表中的只读包装的新实例。

更新: 我没有看到ReadOnlyCollection<T>Items保护。

+0

我更喜欢'.ToArray()'。更简单的IMO! –

+1

@KierenJohnstone可能也比较慢。 –

回答

36

如果你只是返回一个实际的List<T>作为IReadOnlyList<T>,那么调用者总是可以将其抛弃,然后根据需要修改列表。相反,调用AsReadOnly()会创建列表的只读包装,消费者无法更新。

请注意,只读封装将反映对底层列表所做的更改,因此具有对原始列表的访问权限的代码仍然可以更新,只要只读版本的任何使用者都能看到这些更改。

+0

但是我可以抛出'AsReadOnly()。Items',不是吗? – mayu

+5

@Tymek你不能:'AsReadOnly()'创建一个新的,非'List '类,它没有允许基础列表变种的公共方法。 ('项目'是*'protected' *,因此随机的消费者无法访问它。) – dlev

+0

项目不是原始列表,您不能更改原始列表。 – Steven

18

所有这并不是说AsReadOnly()加入,因为IReadOnlyList<T>不够好首先 - IReadOnlyList<T>仅适用于.NET 4.5开始,而AsReadOnly()方法,因为.NET存在2

更重要的是:AsReadOnly()IReadOnlyList<T>服务于不同的目的。

ReadOnlyCollection<T>是用于实现对象模型,例如像Dictionary<K,V>.KeysDictionary<K,V>.Values的东西。这适用于消费者不应该能够在生产者可以更改内容的情况下。它与Collection<T>一起使用,它为所有者提供挂钩以验证更改或在项目添加时执行副作用。

IReadOnlyList<T>另一方面只是提供集合的只读视图的界面。方法可以用它来说“我需要一个随机访问集合,但我不需要修改它”。例如,BinarySearch方法可能是这样的:

public int BinarySearch<T>(IReadOnlyList<T> list, int start, int length); 

为了使这种方法很有用,它需要能够在任何列表通过。强制创建包装集合将会非常昂贵。