views:

246

answers:

5

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 :(

A: 

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
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
+ 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
+11  A: 

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 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
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
Ok, I'll keep looking :) Marked as answer as I think it's the most informative one.
Sune Rievers
Changed accepted answer to Steffen's, because his documentation is top notch. This is still a great answer though.
Sune Rievers
@Sune: Bad move... personally I think this answer is streets ahead of Steffen's... straight to the point and a decent example.
demoncodemonkey
@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
+3  A: 

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
Sounds reasonable :)
Sune Rievers
+3  A: 

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
+4  A: 

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
+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