C# Can';不要将keyValuePair直接添加到字典中

C# Can';不要将keyValuePair直接添加到字典中,c#,dictionary,key-value,generic-collections,C#,Dictionary,Key Value,Generic Collections,我想将KeyValuePair添加到Dictionary中,但我做不到。我必须分别传递键和值,这意味着Add方法必须创建一个新的KeyValuePair对象来插入,这不是很有效。我不敢相信Add方法上没有Add(KeyValuePair)重载。有人能提出这种明显疏忽的可能原因吗?您可以使用IDictionary界面,该界面提供了Add(KeyValuePair)方法: IDictionary<int, string> dictionary = new Dictionary<in

我想将
KeyValuePair
添加到
Dictionary
中,但我做不到。我必须分别传递键和值,这意味着Add方法必须创建一个新的KeyValuePair对象来插入,这不是很有效。我不敢相信Add方法上没有
Add(KeyValuePair)
重载。有人能提出这种明显疏忽的可能原因吗?

您可以使用
IDictionary
界面,该界面提供了
Add(KeyValuePair)
方法:

IDictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(new KeyValuePair<int,string>(0,"0"));
dictionary.Add(new KeyValuePair<int,string>(1,"1"));
IDictionary dictionary=newdictionary();
添加(新的键值对(0,“0”);
添加(新的KeyValuePair(1,“1”));

有这样一种方法–
ICollection.Add
,但由于它是显式实现的,您需要将dictionary对象强制转换到该接口以访问它

((ICollection<KeyValuePair<KeyType, ValueType>>)myDict).Add(myPair);
((ICollection)myDict.Add(myPair);

  • 在的文档页面上的显式接口实现列表(您需要向下滚动)

这个方法的示例。

我不是100%确定,但我认为字典的内部实现是一个哈希表,这意味着将键转换为哈希以执行快速查找

如果您想了解更多关于哈希表的信息,请阅读此处


备份一分钟……在走上监督之路之前,您应该确定创建新的KeyValuePair是否真的如此低效


首先,Dictionary类不是作为一组键/值对在内部实现的,而是作为一组数组实现的。除此之外,让我们假设它只是一组KeyValuePairs,然后看看效率

首先要注意的是结构。这意味着它必须从堆栈复制到堆,才能作为方法参数传递。将KeyValuePair添加到字典时,必须再次复制它以确保值类型语义


为了将键和值作为参数传递,每个参数可以是值类型或引用类型。如果它们是值类型,则性能将非常类似于KeyValuePair路由。如果它们是引用类型,这实际上是一个更快的实现,因为只需要传递地址,只需进行很少的复制。在最佳和最坏情况下,由于KeyValuePair结构本身的开销增加,此选项略优于KeyValuePair选项。

仅仅因为Dictionary类的枚举器返回KeyValuePair,并不意味着它是如何在内部实现的


如果确实需要传递KVP,请使用IDictionary,因为您已经获得了该格式的KVP。否则使用赋值或直接使用Add方法。

如果有人真的想这样做,这里有一个扩展

    public static void Add<T, U>(this IDictionary<T, U> dic, KeyValuePair<T, U> KVP)
    {
        dic.Add(KVP.Key, KVP.Value);
    }
公共静态无效添加(此IDictionary dic,KeyValuePair KVP)
{
dic.Add(KVP.Key,KVP.Value);
}

但是如果没有必要这样做,我建议不要这样做,除非我弄错了,.NET 4.5和4.6增加了向字典中添加KeyValuePair的功能。(如果我错了,请通知我,我将删除此答案。)

通过以上链接,相关信息如下代码示例:

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"));

    ...
}
publicstaticvoidmain()
{
//创建一个新的字符串字典,包括字符串键和
//通过通用ICollection接口访问它
//通用ICollection接口将字典视为
//具有相同类型的KeyValuePair对象的集合
//作为字典的参数。
//
ICollection openWith=
新字典();
//在字典中添加一些元素。当元素
//通过ICollection界面添加
//和值必须包装在KeyValuePair对象中。
//
openWith.Add(新的键值对(“txt”,“notepad.exe”);
openWith.Add(新的KeyValuePair(“bmp”、“paint.exe”);
openWith.Add(新的KeyValuePair(“dib”、“paint.exe”);
openWith.Add(新的KeyValuePair(“rtf”、“wordpad.exe”);
...
}

可以看到,创建了一个新的Dictionary类型的对象,称为
openWith
。然后创建一个新的KVP对象,并使用
.Add
方法将其添加到
openWith
中。

将其作为扩展添加到项目中会有什么问题

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);
        }
    }
}
namespace System.Collection.Generic
{
公共静态类字典扩展
{
公共静态无效AddKeyValuePair(此IDictionary me,KeyValuePair其他)
{
me.Add(other.Key,other.Value);
}
}
}

没有这种重载,因为字典不仅仅“插入”新的KeyValuePair。(我甚至怀疑它是否以这种格式存储在引擎盖下)它测试密钥是否已经存在,并可能执行一些操作将其放置在正确的位置,以尽可能快地保持查询;您的键和值的类型是什么?我认为您可以忽略“Add”方法的开销。您也可以使用dictionary.Add(pair.key,pair.value),其中pair是KVP object。请注意,此方法只调用
Add(KVP.key,KVP.value)
@Rawling是的,在大多数情况下都是这样,但这取决于IDictionary接口的实现(例如,排序字典以调用Add(kvp.Key,kvp.Value)以外的其他方式实现它)。尽管正确,但这与问题无关。So-1。(即使是哈希表也需要存储原始值来处理冲突和枚举键。)这个问题显然是由于缺乏对词典内部工作原理的理解。我的回答使他能够自己回答这个问题和进一步的问题,或者至少在哪里寻找答案。我并不完全同意。是的,有假设