我想向一个Dictionary<T, U>
添加一个KeyValuePair<T,U>
,但是我无法这样做。我必须分别传递键和值,这意味着Add方法必须创建一个新的KeyValuePair对象来插入,这可能不是很有效率。我无法相信Add方法上没有Add(KeyValuePair<T, U>)
重载。有人能为这个明显的疏忽提出可能的原因吗?
我想向一个Dictionary<T, U>
添加一个KeyValuePair<T,U>
,但是我无法这样做。我必须分别传递键和值,这意味着Add方法必须创建一个新的KeyValuePair对象来插入,这可能不是很有效率。我无法相信Add方法上没有Add(KeyValuePair<T, U>)
重载。有人能为这个明显的疏忽提出可能的原因吗?
您可以使用 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"));
Add(kvp.Key, kvp.Value)
。 - Rawling备份一下...在进行优化之前,您应该确定创建新的KeyValuePair是否真的效率低下。
首先,Dictionary类并不是内部实现为一组键/值对,而是一组数组。除此之外,让我们假设它只是一组KeyValuePairs并查看效率。
要注意的第一件事是KeyValuePair是一个结构体。这意味着它必须从堆栈复制到堆中,以便作为方法参数传递。当KeyValuePair添加到字典中时,它必须再次复制以确保值类型语义。
为了将Key和Value作为参数传递,每个参数可以是值类型或引用类型。如果它们是值类型,则性能与KeyValuePair路线非常相似。如果它们是引用类型,则这实际上可能是一种更快的实现,因为只需要传递地址,并且几乎不需要复制。在最好情况和最坏情况下,由于KeyValuePair结构本身的增加开销,这个选项比KeyValuePair选项稍微好一些。
Dictionary<K, T>.Entry
的数组(包含键、值和一些整数)。但除此之外,您的想法是正确的(但未提及“过早优化”:-))。 - RichardKeyValuePair<Of TKey,TValue>
的成本与分别复制 TKey
和 TValue
差不多。构造这样的结构体来调用 Add
方法并没有什么帮助,但如果手动枚举 IEnumerator<KeyValuePair<TKey,TValue>>
,则调用 Add(myEnumerator.Current);
比 Add(myEnumerator.Current.Key,myEnumerator.Current.Value);
更有效率。我认为公开重载方法不会有任何问题。 - supercat有这样一个方法 ICollection<KeyValuePair<K, T>>.Add
,但由于它是显式实现,所以需要将您的字典对象转换为该接口才能访问它。
((ICollection<KeyValuePair<KeyType, ValueType>>)myDict).Add(myPair);
请查看:
Dictionary<K, T>
文档页面上的显式接口实现列表(您需要向下滚动)。此方法的页面中包含示例。
((ICollection<KeyValuePair<KeyType, ValueType>>)myDict).Add(myPair);
吗? - nicodemus13 public static void Add<T, U>(this IDictionary<T, U> dic, KeyValuePair<T, U> KVP)
{
dic.Add(KVP.Key, KVP.Value);
}
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"));
...
}
openWith
的新字典类型对象。然后使用.Add
方法创建并将一个新的KVP对象添加到openWith
中。openWith
被声明为 ICollection<KeyValuePair<String, String>>
,尽管它在内部使用了一个 Dictionary<string, string>
。这就是为什么 Add()
方法可用的原因。 - asherber仅仅因为字典类的枚举器返回一个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);
}
}
}
我不是百分之百确定,但我认为字典的内部实现是哈希表,这意味着键被转换为哈希以执行快速查找。
如果您想了解更多关于哈希表的信息,请在此处阅读。