Sun*_*ers 95 c# optimization dictionary
是什么在差异Dictionary.add(key, value)和Dictionary[key] = value?
我注意到最后一个版本ArgumentException在插入重复密钥时没有抛出,但有没有理由更喜欢第一个版本?
编辑:有没有人有权威的信息来源?我尝试过MSDN,但它一如既往的野鹅追逐:(
Ste*_*fen 99
性能几乎完全相同.您可以通过在Reflector.net中打开课程来检查这一点
这是这个索引器:
public TValue this[TKey key]
{
get
{
int index = this.FindEntry(key);
if (index >= 0)
{
return this.entries[index].value;
}
ThrowHelper.ThrowKeyNotFoundException();
return default(TValue);
}
set
{
this.Insert(key, value, false);
}
}
Run Code Online (Sandbox Code Playgroud)
这是Add方法:
public void Add(TKey key, TValue value)
{
this.Insert(key, value, true);
}
Run Code Online (Sandbox Code Playgroud)
我不会发布整个Insert方法,因为它相当长,但方法声明是这样的:
private void Insert(TKey key, TValue value, bool add)
Run Code Online (Sandbox Code Playgroud)
进一步在功能中,这发生了:
if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
{
if (add)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
Run Code Online (Sandbox Code Playgroud)
其中检查密钥是否已存在,如果密钥已存在且参数add为true,则抛出该异常.
因此,出于所有目的和意图,性能是相同的.
像其他一些提到的那样,关键是你是否需要检查,尝试两次添加相同的密钥.
抱歉这篇冗长的帖子,我希望没关系.
hhr*_*avn 67
第一个版本将向字典中添加一个新的KeyValuePair,如果密钥已经在字典中,则抛出.第二个,使用索引器,如果密钥不存在,将添加一个新对,但如果密钥已存在于字典中,则覆盖密钥的值.
IDictionary<string, string> strings = new Dictionary<string, string>();
strings["foo"] = "bar"; //strings["foo"] == "bar"
strings["foo"] = string.Empty; //strings["foo"] == string.empty
strings.Add("foo", "bar"); //throws
Run Code Online (Sandbox Code Playgroud)
Mic*_*tov 29
Dictionary.Add(key, value)并Dictionary[key] = value有不同的目的:
Add方法添加新的键/值对,不会替换现有键(ArgumentException抛出一个).net*_*ero 23
要首先回答这个问题,我们需要看看字典和底层技术的目的.
Dictionary是KeyValuePair<Tkey, Tvalue>每个值由其唯一键表示的位置的列表.假设我们列出了您最喜欢的食物.每个值(食物名称)由其唯一键表示(位置=您喜欢这种食物的程度).
示例代码:
Dictionary<int, string> myDietFavorites = new Dictionary<int, string>()
{
{ 1, "Burger"},
{ 2, "Fries"},
{ 3, "Donuts"}
};
Run Code Online (Sandbox Code Playgroud)
假设你想要保持健康,你已经改变主意,想要用沙拉代替你最喜欢的"汉堡".您的列表仍然是您的收藏夹列表,您不会更改列表的性质.您最喜欢的将保持在列表中的第一位,只有它的值会改变.这是你打电话的时候:
/*your key stays 1, you only replace the value assigned to this key
you alter existing record in your dictionary*/
myDietFavorites[1] = "Salad";
Run Code Online (Sandbox Code Playgroud)
但是不要忘记你是程序员,从现在开始你完成你的句子; 你拒绝使用表情符号,因为它们会抛出编译错误,所有收藏列表都是0索引.
你的饮食也改变了!所以你再次改变你的清单:
/*you don't want to replace Salad, you want to add this new fancy 0
position to your list. It wasn't there before so you can either define it*/
myDietFavorites[0] = "Pizza";
/*or Add it*/
myDietFavorites.Add(0, "Pizza");
Run Code Online (Sandbox Code Playgroud)
定义有两种可能性,您要么为之前不存在的内容提供新定义,要么想要更改已存在的定义.
Add方法允许您添加记录但仅在一个条件下:您的字典中可能不存在此定义的键.
现在我们来看看幕后.当您创建字典时,编译器会对存储区进行预留(内存中的空格用于存储记录).存储桶不会以您定义它们的方式存储密钥.每个密钥在进入存储桶(由Microsoft定义)之前进行哈希处理,值得一提的是值部分保持不变.
我将使用CRC32哈希算法来简化我的示例.当你定义:
myDietFavorites[0] = "Pizza";
Run Code Online (Sandbox Code Playgroud)
这是怎么回事给水桶db2dc565 "比萨"(简化).
当您使用以下内容更改值时:
myDietFavorites[0] = "Spaghetti";
Run Code Online (Sandbox Code Playgroud)
你将你的0再次作为db2dc565,然后你在桶中查找这个值,看它是否在那里.如果它在那里你只需重写分配给键的值.如果它不在那里你将把你的价值放在桶里.
当您在字典上调用Add函数时,例如:
myDietFavorite.Add(0, "Chocolate");
Run Code Online (Sandbox Code Playgroud)
您对0进行散列以将其值与桶中的值进行比较.只有当它不存在时,您可以将它放在桶中.
了解它是如何工作的至关重要,特别是如果你使用字符串或char类型的键字典.它因为经历散列而区分大小写.例如"name"!="Name".让我们用CRC32来描述这个.
"name"的值为:e04112b1 "Name"的值为:1107fb5b