Thursday, August 1, 2013

Dictionary: Indexer Setter Can Add New Item

Did you know that the following test passes instead of failing with an exception?

[TestMethod]
public void WriteAccessToNonExistingKeyAddsTheElement()
{
   var dict = new Dictionary<string, object>();
   dict["NonExistingKey"] = new object();
   Assert.AreEqual(1, dict.Count);
}

What I learned today is, that you can add an item to a dictionary by just assigning it using the indexer setter where I had expected an exception.

Does this mean, that should happily use this indexer syntax to add new elements to a dictionary?
No!

Here's my reasoning:

1. It is semantically wrong

What does a line like this say?

   dict[aKey] = aValue;

It says: Set the value for the item in the dictionary associated to the key aKey. Trying to do this for a key that has not been added to the dictionary at all, does not make sense.

Therefore I would expect an exception.

2. It is inconsistent

A read access to the indexer with a non existing key throws an exception. So it seems inconsistent to get no exception in the write case.

3. It is unexpected

Of course, letting the behaviour of the index setter being as it is, was a valid design decision. But I think it is an absolutely unexpected behaviour. There are explicit Add(...) methods in the Dictionary-class. The name of these methods are absolutely clear. They say that they do. So why not make these the only means to add an item?


Conclusion

To make your code readable, use an Add(...) overload. To change the value of an existing item in the dictionary, use the indexer setter.

Please.