Different ways of adding to Dictionary

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.


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     

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


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.