[英]Why does F# map implement the interfaces with mutable operations?
當我意識到F#的map
實現IDictionary <'Key,'Value>和ICollection<KeyValuePair<'a, 'b>>
考慮到作為合同一部分支持突變(添加和刪除)時,我感到有些驚訝。
在map
的實現時,它只是在您嘗試引起突變時的例外!
let map = [| (1, "one"); (2, "two") |] |> Map.ofArray
let dict = map :> IDictionary<int, string>
dict.Add(3, "three");;
上面的代碼拋出異常:
System.NotSupportedException:不能對映射值進行突變。 在Microsoft.FSharp.Collections.FSharpMap中
2.System-Collections-Generic-IDictionary
2-Add(TKey k,TValue v)在。$ FSI_0007.main @()處由於錯誤而停止
正如預期的那樣。
對於一個不可變的集合來說,僅當該集合的使用者試圖引起突變時才拋出異常,才能夠將自己暴露為可變的,這似乎是一個危險的決定。
我在這里想念什么嗎?
我認為主要原因是.NET沒有任何表示不可變(一個接口的一部分)字典的接口。 這意味着所有.NET API即使僅打算從字典中讀取,也必須采用IDictionary<K, V>
作為參數。 所以:
實現IDictionary<'K, 'V>
幾乎是使F#不變映射可用作需要需要支持對象的任何.NET庫的參數的唯一方法。 可悲的是,.NET中沒有只讀替代方法。
對我來說,實現ICollection<KeyValuePair<'K, 'V>>
並沒有太大意義,因為有一個只讀替代IEnumerable<KeyValuePair<'K, 'V>>
並且不可變映射也實現了此接口。
但是也許有些.NET庫采用ICollection<'T>
(以提高效率-即在不枚舉所有元素的情況下獲取Count
)並以只讀方式使用它。
編輯:正如Daniel在評論中所指出的,實現ICollection
是必需的,因為IDictionary
接口繼承自它。
我認為很遺憾缺少只讀接口,但是可能無法解決此問題,因為這將意味着更改現有的.NET集合庫。
IsReadOnly
允許接口為只讀,即使它提供了可寫的方法。
這是一個.Net的東西。 您不能只實現某些接口,而他們卻想實現IDictionary`2
接口-因為您可以使用其查詢和轉換方法(因此您可以將其傳遞給從IDictionary`2
讀取的函數)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.