2013-07-01 36 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); 

爲了使這種方法很有用,它需要能夠在任何列表通過。強制創建包裝集合將會非常昂貴。