2012-06-20 6 views
8

F#のmapがIDictionary < 'Key、' Value>とICollection<KeyValuePair<'a, 'b>>の両方を実装していることが、契約の一部として突然変異(追加と削除)をサポートしていることを考慮すると、少し驚きました。F#マップは、変更可能な操作のインターフェイスを実装するのはなぜですか?

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-追加で(TKEY K、TValue vを)。$ FSI_0007.main @()が期待通りである

をエラーに起因する を停止しました。

不変なコレクションが、そのコレクションのコンシューマが突然変異を起こそうとしたときに例外をスローするための変更可能なコレクションとして公開できるようにするには、このような危険な決定があるようです。

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

+2

['dict'](http://msdn.microsoft.com/en-us/library/ee353774.aspx)関数もそのような例です。 _read only_ 'IDictionary <_,_>'を返します。 – Daniel

答えて

6

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

+0

良い点ですが、消費者は常にそのプロパティの値をチェックすることになりますが、それは十分だと思います – theburningmonk

4

これは.Netのものです。インターフェイスの一部だけを実装することはできませんが、IDictionary`2インターフェイスを実装する必要がありました。クエリメソッドと変換メソッドを使用できるため(IDictionary`2から読み取る関数に渡すことができます)。

9

私は主な理由は、.NETには不変の(aのインターフェイスの一部)辞書を表すインターフェイスがないと思います。つまり、すべての.NET APIは、辞書からの読み取りのみを意図していても、パラメータとしてIDictionary<K, V>を使用する必要があります。だから、:IDictionary<'K, 'V>を実装

  • はかなりのルックアップをサポートするオブジェクトを必要とする任意の.NETライブラリへのパラメータとして使用可能なF#不変のマップを作成するための唯一の方法です。悲しいことに、.NETには読み取り専用の代替手段はありません。

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

    ICollection<'T>(すべての要素を列挙しないでCountを取得する)効率的に使用する一部の.NETライブラリがあり、読み取り専用の方法で使用します。

    編集:コメントにダニエルによって述べたようにIDictionaryインタフェースはそれから継承するためICollectionを実装することは、必要とされます。

私は読み取り専用インターフェースの欠如は非常に不幸だと思うが、それは既存の.NETのコレクションライブラリを変更することを意味しますので、これは修正されることができる方法は、おそらくありません。

+3

'' IDictionary <_,_> '](http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx)が継承するため、' Map'は 'ICollection >を実装する必要があります。 – Daniel

+0

@ダニエル素晴らしいポイント - ありがとう!私は答えを編集します。 –

関連する問題