C# 添加到字典的不同方式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1838476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 21:17:40  来源:igfitidea点击:

Different ways of adding to Dictionary

c#optimizationdictionary

提问by Sune Rievers

What is the difference in Dictionary.add(key, value)and Dictionary[key] = value?

是什么在差异Dictionary.add(key, value)Dictionary[key] = value

I've noticed that the last version does not throw an ArgumentExceptionwhen inserting a duplicate key, but is there any reason to prefer the first version?

我注意到最后一个版本ArgumentException在插入重复键时不会抛出 an ,但是有什么理由更喜欢第一个版本吗?

Edit: Does anyone have an authoritative source of information about this? I've tried MSDN, but it is as always a wild goose chase :(

编辑:有没有人有这方面的权威信息来源?我试过 MSDN,但它一如既往地追逐野鹅:(

采纳答案by Steffen

The performance is almost a 100% identical. You can check this out by opening the class in Reflector.net

性能几乎 100% 相同。您可以通过在 Reflector.net 中打开类来检查这一点

This is the This indexer:

这是 This 索引器:

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

And this is the Add method:

这是 Add 方法:

public void Add(TKey key, TValue value)
{
    this.Insert(key, value, true);
}

I won't post the entire Insert method as it's rather long, however the method declaration is this:

我不会发布整个 Insert 方法,因为它很长,但是方法声明是这样的:

private void Insert(TKey key, TValue value, bool add)

And further down in the function, this happens:

在函数的更深处,会发生这种情况:

if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
{
    if (add)
    {
        ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
    }

Which checks if the key already exists, and if it does and the parameter add is true, it throws the exception.

它检查键是否已经存在,如果存在并且参数 add 为真,则抛出异常。

So for all purposes and intents the performance is the same.

因此,对于所有目的和意图,性能都是相同的。

Like a few other mentions, it's all about whether you need the check, for attempts at adding the same key twice.

与其他一些提及一样,这完全是关于您是否需要检查,以尝试添加相同的密钥两次。

Sorry for the lengthy post, I hope it's okay.

抱歉,帖子太长了,希望没事。

回答by Jorge Córdoba

Given the, most than probable similarities in performance, use whatever feel more correct and readable to the piece of code you're using.

考虑到性能上最可能的相似之处,请使用对您正在使用的代码段来说更正确和更易读的任何内容。

I feel an operation that describes an addition, being the presence of the key already a really rare exception is best represented with the add. Semantically it makes more sense.

我觉得一个描述添加的操作,因为键的存在已经是一个非常罕见的异常,最好用添加来表示。从语义上讲,它更有意义。

The dict[key] = valuerepresents better a substitution. If I see that code I half expect the key to already be in the dictionary anyway.

dict[key] = value代表更好的替代。如果我看到该代码,我一半希望密钥无论如何都已经在字典中了。

回答by hhravn

The first version will add a new KeyValuePair to the dictionary, throwing if key is already in the dictionary. The second, using the indexer, will add a new pair if the key doesn't exist, but overwrite the value of the key if it already exists in the dictionary.

第一个版本将向字典添加一个新的 KeyValuePair,如果 key 已经在字典中,则抛出。第二个,使用索引器,如果键不存在,将添加一个新对,但如果它已经存在于字典中,则覆盖键的值。

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     

回答by Guffa

Yes, that is the difference, the Add method throws an exception if the key already exists.

是的,这就是区别,如果键已经存在,Add 方法会抛出异常。

The reason to use the Add method is exactly this. If the dictionary is not supposed to contain the key already, you usually want the exception so that you are made aware of the problem.

使用Add方法的原因正是如此。如果字典不应该已经包含键,您通常需要异常以便您意识到问题。

回答by Michael Damatov

Dictionary.Add(key, value)and Dictionary[key] = valuehave different purposes:

Dictionary.Add(key, value)Dictionary[key] = value有不同的目的:

  • Use the Addmethod to addnew key/value pair, existing keys will not be replaced (an ArgumentExceptionis thrown).
  • Use the indexer if you don't care whether the key already exists in the dictionary, in other words: add the key/value pair if the the key is not in the dictionary or replace the value for the specified key if the key is already in the dictionary.
  • 使用该Add方法添加新的键/值对,现有键不会被替换(ArgumentException抛出an )。
  • 如果您不关心键是否已存在于字典中,请使用索引器,换句话说:如果键不在字典中,则添加键/值对,如果键已经存在,则替换指定键的值在字典里。

回答by Joshua Smith

One is assigning a value while the other is adding to the Dictionary a new Key and Value.

一个是分配一个值,另一个是向字典添加一个新的键和值。

回答by Kamil Kurzynowski

To answer the question first we need to take a look at the purpose of a dictionary and underlying technology.

首先要回答这个问题,我们需要看一下字典的目的和底层技术。

Dictionaryis the list of KeyValuePair<Tkey, Tvalue>where each value is represented by its unique key. Let's say we have a list of your favorite foods. Each value (food name) is represented by its unique key (a position = how much you like this food).

DictionaryKeyValuePair<Tkey, Tvalue>每个值由其唯一键表示的位置的列表。假设我们有一份您最喜欢的食物清单。每个值(食物名称)由其唯一键表示(位置 = 您喜欢这种食物的程度)。

Example code:

示例代码:

Dictionary<int, string> myDietFavorites = new Dictionary<int, string>()
{
    { 1, "Burger"},
    { 2, "Fries"},
    { 3, "Donuts"}
};

Let's say you want to stay healthy, you've changed your mind and you want to replace your favorite "Burger" with salad. Your list is still a list of your favorites, you won't change the nature of the list. Your favorite will remain number one on the list, only it's value will change. This is when you call this:

假设您想保持健康,您改变了主意,想用沙拉代替您最喜欢的“汉堡”。您的列表仍然是您最喜欢的列表,您不会改变列表的性质。您最喜欢的将保持在列表中的第一名,只是它的价值会发生变化。这是你调用它的时候:

/*your key stays 1, you only replace the value assigned to this key
  you alter existing record in your dictionary*/
myDietFavorites[1] = "Salad";

But don't forget you're the programmer, and from now on you finishes your sentences with ; you refuse to use emojis because they would throw compilation error and all list of favorites is 0 index based.

但是不要忘记你是程序员,从现在开始你用; 结束你的句子。您拒绝使用表情符号,因为它们会引发编译错误,并且所有收藏夹列表都是基于 0 索引的。

Your diet changed too! So you alter your list again:

你的饮食也变了!所以你再次改变你的清单:

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

There are two possibilities with defining, you either want to give a new definition for something not existent before or you want to change definition which already exists.

定义有两种可能性,您要么想为以前不存在的东西提供新定义,要么想更改已经存在的定义。

Add method allows you to add a record but only under one condition: key for this definition may not exist in your dictionary.

Add 方法允许您添加记录,但仅限于一种条件:此定义的键可能不存在于您的字典中。

Now we are going to look under the hood. When you are making a dictionary your compiler make a reservation for the bucket (spaces in memory to store your records). Bucket don't store keys in the way you define them. Each key is hashed before going to the bucket (defined by Microsoft), worth mention that value part stays unchanged.

现在我们要看看引擎盖下。当您制作字典时,您的编译器会为存储桶(用于存储记录的内存空间)预留空间。Bucket 不会按照您定义的方式存储密钥。每个键在进入存储桶(由微软定义)之前都经过哈希处理,值得一提的是值部分保持不变。

I'll use the CRC32 hashing algorithm to simplify my example. When you defining:

我将使用 CRC32 散列算法来简化我的示例。当你定义:

myDietFavorites[0] = "Pizza";

What is going to the bucket is db2dc565"Pizza" (simplified).

进入桶的是db2dc565"Pizza"(简化)。

When you alter the value in with:

当您更改值时:

myDietFavorites[0] = "Spaghetti";

You hash your 0 which is again db2dc565then you look up this value in your bucket to find if it's there. If it's there you simply rewrite the value assigned to the key. If it's not there you'll place your value in the bucket.

您对 0 进行哈希处理,这又是db2dc565,然后您在存储桶中查找该值以查找它是否存在。如果它在那里,您只需重写分配给键的值。如果它不存在,您会将您的价值放入存储桶中。

When you calling Add function on your dictionary like:

当您在字典上调用 Add 函数时,例如:

myDietFavorite.Add(0, "Chocolate");

You hash your 0 to compare it's value to ones in the bucket. You may place it in the bucket only if it's not there.

您散列 0 以将其值与存储桶中的值进行比较。只有当它不存在时,您才可以将它放入桶中。

It's crucial to know how it works especially if you work with dictionaries of string or char type of key. It's case sensitive because of undergoing hashing. So for example "name" != "Name". Let's use our CRC32 to depict this.

了解它是如何工作的至关重要,尤其是当您使用字符串或字符类型的键字典时。由于经过哈希处理,因此区分大小写。因此,例如“名称”!=“名称”。让我们使用我们的 CRC32 来描述这一点。

Value for "name" is: e04112b1Value for "Name" is: 1107fb5b

“名称”的值为:e04112b1“名称”的值为:1107fb5b

回答by Maghalakshmi Saravana

To insert the Value into the Dictionary

将值插入字典

 Dictionary<string, string> dDS1 = new Dictionary<string, string>();//Declaration
 dDS1.Add("VEqpt", "aaaa");//adding key and value into the dictionary
 string Count = dDS1["VEqpt"];//assigning the value of dictionary key to Count variable
 dDS1["VEqpt"] = Count + "bbbb";//assigning the value to key