为什么dict允许重复插入?

时间:2015-06-23 18:12:58

标签: f#

为什么世界上F#中字典的构造函数允许重复键并且只是静默覆盖?

let ``you just got dict`` = dict [ "hello","goodbye";"hello","world"]

这是非常违反直觉的行为。

3 个答案:

答案 0 :(得分:3)

您可以使用行为符合您想要的版本来遮蔽内置dict函数。你可以在你接触时返回更合适的IReadOnlyDictionary界面。

let dict source =
    let d = Dictionary<'K, 'V>(HashIdentity.Structural)
    source |> Seq.iter d.Add
    { 
        new IReadOnlyDictionary<'K, 'V> with
            member x.ContainsKey(key) = d.ContainsKey(key)
            member x.TryGetValue(key, value) = d.TryGetValue(key, &value)
            member x.Item with get key = d.[key]
            member x.Keys = d.Keys :> _
            member x.Values = d.Values :> _
        interface IReadOnlyCollection<KeyValuePair<'K, 'V>> with
            member x.Count = d.Count
        interface IEnumerable<KeyValuePair<'K, 'V>> with
            member x.GetEnumerator() = d.GetEnumerator() :> _
        interface System.Collections.IEnumerable with
            member x.GetEnumerator() = d.GetEnumerator() :> _
    }

答案 1 :(得分:1)

我无法解释此设计的原因 - 正如我无法解释 why Dictionary<TKey, TValue> doesn't take a sequence of KeyValuePairs as input

但是,如果你看一下dict的实现,你会看到它在内部使用索引器添加每个元素,如下所示:

foreach (Tuple<TKey, TValue> tuple in keyValuePairs)
{
    TValue local = tuple.Item2;
    TKey local2 = tuple.Item1;
    d[new RuntimeHelpers.StructBox<TKey>(local2)] = local;
}

其中d是正在创建的Dictionary。索引器以静默方式更新字典条目,因此这解释了它的机制。

我承认,这不是一个完整的答案,但也许是一个难题。

答案 2 :(得分:0)

除非一些微软工程师向你解释为什么他们选择这样做,否则你不会得到原因。无论如何,它就是它的本质,并且正如文档所说的那样:

https://msdn.microsoft.com/en-us/library/k7z0zy8k(v=vs.110).aspx

Remarks

You can also use the Item property to add new elements by setting the value
of a key that does not exist in the Dictionary<TKey, TValue>; for example, 
myCollection[myKey] = myValue (in Visual Basic, myCollection(myKey) = 
myValue). However, if the specified key already exists in the 
Dictionary<TKey, TValue>, setting the Item property overwrites the old 
value. In contrast, the Add method throws an exception if a value with the 
specified key already exists.