Sunday 29 June 2014

C# 6 Dictionary Initializers

I already wrote back in December how little excited I was about the (at that time not confirmed) new features in C#. I've confirmed that feeling over the last months (well, at least it seems like the Safe Navigation Operator (called Null Propagation here) is finally making it into the language). I find most of the features (setting Roslyn aside) add little value (and sometimes add confusion).

One of the features really got me confused, but hopefully other developers found it weird too, and Eric Lippert gave a clear explanation in StackOverflow, that once again made it evident how important it is to understand what the compiler is doing under the covers (well, in this case it was not a matter of decompiling anything, but a matter of having taken the time to fully read the documentation).

So, C# 6 is adding Dictionary Initializers, that is:

 var departments = new Dictionary<String, int> {
["Haute-Garonne"] = 31, 
["Gironde"] = 33 
};

It gave me sort of a Deja Vu feeling, don't we already have this? In C# we've been able to write this since Object and Collection Initializers were introduced along with Linq:

var departments = new Dictionary<String, int> {
{"Haute-Garonne",31}, 
{"Gironde", 33}
};

So, are we duplicating syntax for doing just the same? The answer is that for this particular type, System.Collections.Generic.Dictionary, both syntaxes achieve the same (though using different code underneath), but there are classes for which the first syntax won't work and the second will do. Let's see:

In the second case, as I said, we're using a Collection Initializer to initialize a Dictionary. This means that our class has to implement IEnumerable, and has to contain an Add method. Under the covers the compiler will transfor these assignments into calls to Add.

In the first case, Dictionary Initializers, no Add method is used, but an Indexer. So in principle, any class featuring an Indexer can be initialized this way. This is obviously more powerful than Collection Initializers and really adds value to the language.

By the way, I've just seen that the proposed new syntax for string indexed members (obj.$name <=> obj["name"]) seems to have been withdrawn. Honestly I think this has been the right decision, that syntax didn't seem to add anything to me.

This is the original question in StackOverflow that helped me understand the whole thing.

I don't understand the dictionary initializer thing. The counterexamples that keep getting given are m = new Dictionary(); m[1] = 2; and so on. But we already have a real dictionary initializer syntax: new Dictionary { { 1, 2 }, { 3, 4 } }. Any idea why we needed another syntax for it? - Aaronaught Apr 6 at 15:13

@Aaronaught: Are you guaranteed that all dictionary objects have an Add method that takes pairs? Suppose for example you have an object that represents an XML document where element["attr"] = "value" is legal. Do we have a guarantee that this object has a method Add that happens to take two strings and adds an attribute-value pair? It seems plausible that the author of that object neglected to implement such a method. – Eric Lippert Apr 6 at 15:18

No comments:

Post a Comment