1

I've just read this question.

If we have property of dictionary type:

public class Test
{
    public Dictionary<string, string> Dictionary { get; set; } = new Dictionary<string, string>
    {
        {"1", "1" },
        {"2", "2" },
    };
}

Then we can construct object and add value to it

 var test = new Test { Dictionary = { { "3", "3" } } };
 Console.WriteLine(test.Dictionary.Count); // 3

And I don't understand the point why such a confusing syntax to add items exists? When looking at someone else code it's very easy to confuse it with very similarly looking

 var test = new Test { Dictionary = new Dictionary<string, string> { { "3", "3" } } };
 Console.WriteLine(test.Dictionary.Count); // 1

I'd be more OK with it if following would be possible (but it's not):

var dictionary = new Dictionary<string, string> { { "1", "1" } };
...
// adding a new value
dictionary = { { "2" , "2"} }; // invalid expression term '{'

So why this form of adding was needed and exists? For interviews?

Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • 1
    To make code more concise - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers#collection-initializers . I agree that, in practice, you want to avoid using it (without the `new`). – mjwills Mar 23 '18 at 12:57
  • 6
    I had the same thought, good question... quite opinion-based though. – hardkoded Mar 23 '18 at 13:00
  • Should be noted that it only comes into play when nested inside another initializer. Basically if done correctly you can initialize a complex object and it's dependencies in "one line" avoiding a lot of repeated syntax. – juharr Mar 23 '18 at 13:04
  • @TimSchmelter That does not create the dictionary. That will only work if `Test` creates the dictionary during construction, then the `{ { "", "" } }` is just calling `Add` on that instance. – juharr Mar 23 '18 at 13:12
  • So an initialize has some shortcuts that don't make sense in an assignment (or are not implemented). – paparazzo Mar 23 '18 at 13:44

2 Answers2

3

The collection initializer syntax is simply a convenient way of initializing collections (including dictionaries) as part of a complex object model using an object initializer. For example:

var model = new SomeModel {
   Name = "abc",
   Id = 42,
   SpecialMaps = {
       { "foo", "bar" },
       { "magic", "science" },
   }
};

If you don't like it: just don't use it; but the equivalent with manual .Add is IMO much less elegant - a lot of things are taken care of automatically, such as only reading the property once. The longer version that actually creates the collection at the same time works very similarly.

Note that there is also an indexer variant now:

var model = new SomeModel {
   Name = "abc",
   Id = 42,
   SpecialMaps = {
       ["foo"] = "bar",
       ["magic"] ="science",
   }
};

This is very similar, but instead of using collection.Add(args); it uses collection[key] = value;. Again, if it confuses you or offends you: don't use it.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 2
    That assignment `=` means Add I would say is kind of confusing, but I assume can come in quite handy. – Magnus Mar 23 '18 at 13:36
  • 1
    @Magnus, exactly. It's an assignment, which is not assigning object from right side, but like a union and it doesn't have distinct enough syntax. Missing `new` is easy to miss. I wouldn't complain if that syntax of *union* would be possible outside of constructing object. I'll accept this answer, but I had a hope for some interesting background of why it was made like this. – Sinatr Mar 23 '18 at 14:03
  • 1
    They should have used `+=` instead :-) – Magnus Mar 23 '18 at 14:05
  • @Magnus, aye, `dictionary += { {"2", "2"}, {"3", "3"} };` would be quite handy instead of multiple `dictionary.Add()`. Worth to [request a feature](https://stackoverflow.com/q/616164/1997232)? But that wouldn't change what has been done already. /facepalm – Sinatr Mar 23 '18 at 14:20
1

Take this example where the constructor of Thing creates a Stuff and the constructor of Stuff creates the Foo list

var thing = new Thing();
thing.Stuff.Foo.Add(1);
thing.Stuff.Foo.Add(2);
thing.Stuff.Foo.Add(3);

And now you can simplify it to the following with initializers.

var thing = new Thing 
{
    Stuff.Foo = { 1, 2, 3 }
};

You can only use this type of initialization for a collection without first newing up the collection when nested because the collection can exist in this case, but cannot when assigning directly to a variable.

Ultimately this type of syntactic sugar is likely added by the language designers when they see code patterns that they think can be simplified.

juharr
  • 31,741
  • 4
  • 58
  • 93