我想将 a 添加KeyValuePair<T,U>
到 a 中Dictionary<T, U>
,但我不能。我必须分别传递key和value,这意味着Add方法必须创建一个新的KeyValuePair对象来插入,效率不高。我不敢相信Add(KeyValuePair<T, U>)
Add 方法没有重载。任何人都可以提出这种明显疏忽的可能原因吗?
8 回答
您可以使用IDictionary<TKey,TValue>
提供Add(KeyValuePair<TKey,TValue>)
方法的接口:
IDictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(new KeyValuePair<int,string>(0,"0"));
dictionary.Add(new KeyValuePair<int,string>(1,"1"));
备份一分钟......在继续监督之前,您应该确定创建新的 KeyValuePair 是否真的如此低效。
首先,Dictionary 类不是在内部实现为一组键/值对,而是作为一组数组。除此之外,让我们假设它只是一组 KeyValuePairs 并查看效率。
首先要注意的是KeyValuePair是一个结构体。真正的含义是它必须从堆栈复制到堆才能作为方法参数传递。当 KeyValuePair 添加到字典中时,必须再次复制它以确保值类型语义。
为了将 Key 和 Value 作为参数传递,每个参数可以是值类型,也可以是引用类型。如果它们是值类型,则性能将与 KeyValuePair 路由非常相似。如果它们是引用类型,这实际上可以是一个更快的实现,因为只需要传递地址并且几乎不需要进行复制。在最好的情况和最坏的情况下,由于 KeyValuePair 结构本身的开销增加,此选项比 KeyValuePair 选项略好。
有这样一种方法——ICollection<KeyValuePair<K, T>>.Add
但由于它是显式实现的,因此您需要将字典对象转换为该接口才能访问它。
((ICollection<KeyValuePair<KeyType, ValueType>>)myDict).Add(myPair);
看
- 的文档页面上的显式接口实现列表
Dictionary<K, T>
(您需要向下滚动)。 - 显式成员实现
此方法的页面包含一个示例。
如果有人真的想这样做,这里有一个扩展
public static void Add<T, U>(this IDictionary<T, U> dic, KeyValuePair<T, U> KVP)
{
dic.Add(KVP.Key, KVP.Value);
}
但如果没有真正需要这样做,我建议不要这样做
除非我弄错了,.NET 4.5 和 4.6 添加了将 KeyValuePair 添加到字典的功能。(如果我错了,请通知我,我会删除这个答案。)
https://msdn.microsoft.com/en-us/library/cc673027%28v=vs.110%29.aspx
从上面的链接中,相关的信息是这个代码示例:
public static void Main()
{
// Create a new dictionary of strings, with string keys, and
// access it through the generic ICollection interface. The
// generic ICollection interface views the dictionary as a
// collection of KeyValuePair objects with the same type
// arguments as the dictionary.
//
ICollection<KeyValuePair<String, String>> openWith =
new Dictionary<String, String>();
// Add some elements to the dictionary. When elements are
// added through the ICollection<T> interface, the keys
// and values must be wrapped in KeyValuePair objects.
//
openWith.Add(new KeyValuePair<String,String>("txt", "notepad.exe"));
openWith.Add(new KeyValuePair<String,String>("bmp", "paint.exe"));
openWith.Add(new KeyValuePair<String,String>("dib", "paint.exe"));
openWith.Add(new KeyValuePair<String,String>("rtf", "wordpad.exe"));
...
}
可以看出,创建并调用了 Dictionary 类型的新对象openWith
。openWith
然后使用该.Add
方法创建并添加一个新的 KVP 对象。
仅仅因为 Dictionary 类的枚举器返回一个 KeyValuePair,并不意味着它在内部是如何实现的。
如果您确实需要通过 KVP,请使用 IDictionary,因为您已经以该格式获得了它们。否则使用赋值或仅使用 Add 方法。
将它作为扩展添加到您的项目中会有什么问题?
namespace System.Collection.Generic
{
public static class DictionaryExtensions
{
public static void AddKeyValuePair<K,V>(this IDictionary<K, V> me, KeyValuePair<K, V> other)
{
me.Add(other.Key, other.Value);
}
}
}
我不是 100% 确定,但我认为 Dictionary 的内部实现是一个哈希表,这意味着键被转换为哈希以执行快速查找。
如果您想了解有关哈希表的更多信息,请阅读此处