Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is this C# dictionary initialization correct?

I stumbled upon the following and I'm wondering why it didn't raise a syntax error.

var dict = new Dictionary<string, object> {     ["Id"] = Guid.NewGuid(),     ["Tribes"] = new List<int> { 4, 5 },     ["MyA"] = new Dictionary<string, object>     {         ["Name"] = "Solo",         ["Points"] = 88     }     ["OtherAs"] = new List<Dictionary<string, object>>     {         new Dictionary<string, object>         {             ["Points"] = 1999         }     } }; 

Notice that the "," is missing between the "MyA", and "OtherAs".

This is where the confusion happens:

  1. The code compiles.
  2. The final dictionary "dict" contains only three elements: "Id", "Tribes", and "MyA".
  3. The value for all except "MyA" are correct,
  4. "MyA" takes the declared value for "OtherAs", while its original value is ignored.

Why isn't this illegal? Is this by design?

like image 905
Dantte Avatar asked Feb 02 '20 09:02

Dantte


People also ask

Is there a this keyword in C?

In C you do not have the this keyword. Only in C++ and in a class, so your code is C and you use your this variable as a local method parameter, where you access the array struct.

What is || in C programming?

Logical OR operator: || The logical OR operator ( || ) returns the boolean value true if either or both operands is true and returns false otherwise.


1 Answers

The missing comma makes all the difference. It causes the indexer ["OtherAs"] to be applied on this dictionary:

new Dictionary<string, object> {     ["Name"] = "Solo",     ["Points"] = 88 } 

So essentially you're saying:

new Dictionary<string, object> {     ["Name"] = "Solo",     ["Points"] = 88 }["OtherAs"] = new List<Dictionary<string, object>> {     new Dictionary<string, object>     {         ["Points"] = 1999     } }; 

Note that this is an assignment expression (x = y). Here x is dictionary with "Name" and "Points", indexed with "OtherAs" and y is the List<Dictionary<string, object>>. An assignment expression evaluates to the value being assigned (y), which is the list of dictionaries.

The result of this whole expression is then assigned to the key "MyA", which is why "MyA" has the list of dictionaries.

You can confirm that this is what's happening by changing the type of the dictionary x:

new Dictionary<int, object> {     [1] = "Solo",     [2] = 88 } // compiler error saying "can't convert string to int" // so indeed this indexer is applied to the previous dictionary ["OtherAs"] = new List<Dictionary<string, object>> {     new Dictionary<string, object>     {         ["Points"] = 1999     } } 

Here is your code, but reformatted and some parentheses added to illustrated how the compiler has parsed it:

["MyA"]  =  (     (         new Dictionary<string, object>         {             ["Name"] = "Solo",             ["Points"] = 88         }["OtherAs"]      )     =      (         new List<Dictionary<string, object>>         {             new Dictionary<string, object>             {                 ["Points"] = 1999             }         }     ) ) 
like image 169
Sweeper Avatar answered Sep 30 '22 06:09

Sweeper