8

mapF#が 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-IDictionary2-Add(TKey k, TValue v) で .$FSI_0007.main@() エラーのため停止しました

これは予想どおりです。

そのコレクションの消費者が突然変異を引き起こそうとしたときに例外をスローするためだけに、不変コレクションがそれ自体を可変コレクションとして公開できるようにすることは、非常に危険な決定のようです。

ここで何か不足していますか?

4

3 に答える 3

9

主な理由は、.NET には不変 (a のインターフェイスの一部) 辞書を表すインターフェイスがないためだと思います。IDictionary<K, V>つまり、ディクショナリからの読み取りのみを目的としている場合でも、すべての .NET API がパラメーターとして受け取る必要があります。そう:

  • IDictionary<'K, 'V>F# 不変マップを、ルックアップをサポートするオブジェクトを必要とする .NET ライブラリへのパラメーターとして使用できるようにする唯一の方法は、実装することです。残念ながら、.NET には読み取り専用の代替手段はありません。

  • 読み取り専用の代替手段があり、不変のマップもこのインターフェースを実装しているため、実装ICollection<KeyValuePair<'K, 'V>>することはあまり意味がありません。IEnumerable<KeyValuePair<'K, 'V>>

    ICollection<'T>しかし、 (効率のために - つまり、Countすべての要素を列挙せずに取得するために) 読み取り専用の方法でそれを使用する .NET ライブラリがいくつかあるかもしれません。

    編集:コメントでダニエルが指摘したように、インターフェイスはそれを継承するICollectionため、実装が必要です。IDictionary

読み取り専用インターフェイスがないことは非常に残念なことだと思いますが、既存の .NET コレクション ライブラリを変更する必要があるため、おそらくこれを修正する方法はありません。

于 2012-06-20T13:59:37.317 に答える
6

IsReadOnly書き込み可能なメソッドを提供していても、インターフェイスを読み取り専用にすることができます。

于 2012-06-20T15:39:17.593 に答える
4

それは.Netのものです。インターフェースの一部だけを実装することはできませんが、彼らはIDictionary`2インターフェースを実装したいと考えていましたIDictionary`2.

于 2012-06-20T13:18:08.527 に答える