147

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

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

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

Sune Rievers
  • 2,676
  • 3
  • 25
  • 29

8 Answers8

147

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

This is the This indexer:

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:

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:

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.

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.

Steffen
  • 13,648
  • 7
  • 57
  • 67
  • 1
    +1 Very interesting, thanks for your post! It would seem that performance is almost identical here, as the other posters have hinted about, anyway great find :) – Sune Rievers Dec 03 '09 at 23:05
  • Whether intentionally, I love that you switched up the order of intents/purposes, thereby dispelling any false understanding of "intensive" purposes among readers. – Nathaniel Jones Oct 28 '22 at 16:47
88

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.

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     
hhravn
  • 1,701
  • 1
  • 10
  • 22
  • +1 Have you got a source for the above information? I'm interested in learning if there are any side effects or caveats in using the first or latter form. – Sune Rievers Dec 03 '09 at 09:46
  • 3
    Don't really have a source as such, just off the top of my head, but i don't think there's much more to it, than mentioned in the other comments. If i remember correctly, Add simply uses the indexer, but checks first to see if the Key is already in use. – hhravn Dec 03 '09 at 10:33
  • 1
    Changed accepted answer to Steffen's, because his documentation is top notch. This is still a great answer though. – Sune Rievers Dec 03 '09 at 23:15
  • @Sune: Bad move... personally I think this answer is streets ahead of Steffen's... straight to the point and a decent example. – demoncodemonkey Apr 28 '10 at 14:11
  • @demoncodemonkey it would seem that the community agrees with you. However, I personally think Steffen's answer was more thorough and informative. It's a matter of taste I think, hhravn's answer is good, short and sweet, but I still prefer Steffen's answer :) – Sune Rievers Apr 28 '10 at 16:58
  • 2
    @SuneRievers I think, it will be more helphul for people, if accepted answer for this, instead of current accepted answer. Because this exactly answers the question ("what's the difference"), rather than the accepted one (that talks about performance, and almost 99% of users searching this topic (like me), needed the "difference" (what why i met this topic), and accepted answer was useless for me and wastes our second. instead, this answer is exact. – T.Todua Sep 07 '17 at 17:35
  • The documentation states this difference between the two types here [link](https://msdn.microsoft.com/en-us/library/k7z0zy8k(v=vs.110).aspx), 'You can also use the Item property to add new elements by setting the value of a key that does not exist in the Dictionary; for example, myCollection[myKey] = myValue (in Visual Basic, myCollection(myKey) = myValue). However, if the specified key already exists in the Dictionary, setting the Item property overwrites the old value. In contrast, the Addmethod throws an exception if a value with the specified key already exists' – aileronajay Jul 10 '18 at 21:55
56

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

Dictionary is 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).

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.

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.

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.

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

myDietFavorites[0] = "Pizza";

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

When you alter the value in with:

myDietFavorites[0] = "Spaghetti";

You hash your 0 which is again db2dc565 then 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.

When you calling Add function on your dictionary like:

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.

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.

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

Quality Catalyst
  • 6,531
  • 8
  • 38
  • 62
nethero
  • 696
  • 5
  • 12
  • This two line is enough to understand ....... 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. – Niraj Trivedi Jun 04 '18 at 04:14
  • 2
    I assume a certain level of knowledge or lack thereof on the side of the person asking this question hence the overexplanation. – nethero Aug 04 '21 at 08:51
38

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

  • Use the Add method to add new key/value pair, existing keys will not be replaced (an ArgumentException is 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.
Michael Damatov
  • 15,253
  • 10
  • 46
  • 71
  • 2
    Code that self-describes intent is important and immensely valuable (and requires little-to-no comments). This answer shows the difference in intent with both methods, and should be followed when choosing one. In other words, don't use the 'indexer add' when you _know ahead of time_ that you will always add, or even _must always_ add. Having an IndexOutOfBounds exception get thrown is better than unexpected behavior. – ryancdotnet Aug 07 '18 at 21:11
5

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

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.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
3

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
0

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] = value represents better a substitution. If I see that code I half expect the key to already be in the dictionary anyway.

Jorge Córdoba
  • 51,063
  • 11
  • 80
  • 130
  • I would assume there is a small performance gain from not checking whether the key exists first. I wouldn't expect from `dic[key] = value` that the key was already present, but I guess that's debatable ;) – Sune Rievers Dec 03 '09 at 08:40
  • 2
    + i think throwing should never be used as a way of checking if the key is already represented. if(!strings.ContainsKey("foo")) strings.Add("foo", "bar"); – hhravn Dec 03 '09 at 09:20
0

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

Joshua Smith
  • 134
  • 10