为什么世界上F#
中字典的构造函数允许重复键并且只是静默覆盖?
let ``you just got dict`` = dict [ "hello","goodbye";"hello","world"]
这是非常违反直觉的行为。
答案 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.