Jaka jest prawidłowa inicjalizacja słownika C#?

Potknąłem się o to i zastanawiam się, dlaczego nie spowodowało to błędu składniowego.

var dict = nowy Słownik<ciąg, obiekt>
{
    ["Id"] = Guid.NewGuid(),
    ["Tribes"] = nowa lista<int> { 4, 5 },
    ["MyA"] = nowy słownik< sznurek, obiekt>
    {
        ["Name"] = "Solo",
        ["Punkty"] = 88
    }
    ["OtherAs"] = nowa lista<Słownik<ciąg, obiekt>>
    {
        Nowy Słownik<ciąg, obiekt>
        {
            ["Punkty"] = 1999 r.
        }
    }
};

Zauważ, że brakuje "," pomiędzy "MyA", a "OtherAs".

To tu się dzieje zamieszanie:

  1. Kod się kompiluje.
  2. Ostateczny słownik "dyktando" zawiera tylko trzy elementy: "Id", "Tribes", i "MyA".
  3. Wartości dla wszystkich oprócz "MyA" są prawidłowe,
  4. "MyA" przyjmuje zadeklarowaną wartość dla "OtherAs", podczas gdy jego pierwotna wartość jest ignorowana.

Dlaczego to nie jest nielegalne? Czy to z założenia?

Uwagi dotyczące pytania (9)
Rozwiązanie

Brakujący przecinek robi całą różnicę. Powoduje on, że na tym słowniku stosowany jest indekser ["OtherAs"]:

new Dictionary
{
    ["Name"] = "Solo",
    ["Points"] = 88
}

Więc w zasadzie mówisz:

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

Zauważ, że jest to wyrażenie przypisania (x = y). Tutaj x jest słownikiem z "Nazwą" i "Punktami", indeksowanym przez "InneAs", a y jest List. Wyrażenie przypisujące ocenia przypisywaną wartość (y), która jest listą słowników.

Wynik tego całego wyrażenia jest następnie przypisywany do klawisza "MyA", dlatego też "MyA" posiada listę słowników.

Możesz potwierdzić, że tak właśnie się dzieje, zmieniając typ słownika x:

new Dictionary
{
    [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
{
    new Dictionary
    {
        ["Points"] = 1999
    }
}

Oto twój kod, ale przeformatowany i kilka nawiasów dodanych do ilustracji jak kompilator go przetworzył:

["MyA"] 
= 
(
    (
        new Dictionary
        {
            ["Name"] = "Solo",
            ["Points"] = 88
        }["OtherAs"] 
    )
    = 
    (
        new List
        {
            new Dictionary
            {
                ["Points"] = 1999
            }
        }
    )
)
Komentarze (2)

To, co się tutaj dzieje, to tworzenie słownika, a następnie indeksowanie do niego. Następnie zwracany jest wynik wyrażenia indexer/assignment i to właśnie jest przypisywane do slotu słownika MyA.

To:

["MyA"] = new Dictionary 
{
   ["Name"] = "Solo",
   ["Points"] = "88" 
}
["OtherAs"] = new List
{
   new Dictionary
   {
       ["Points"] = 1999
   }
}

Może być podzielony na następujące kody psujące:

var temp = new Dictionary
{ 
   ["Name"] = "Solo", 
   ["Points"] = 88 
};
// indexed contains result of assignment
var indexed = temp["OtherAs"] = new List
{
   new Dictionary
   {
      ["Points"] = 1999
   }
};
// value is set to result of assignment from previous step
["MyA"] = indexed;
// temp is discarded

Wynik przypisania do indeksera drugiego słownika jest zwracany (przypisanie zwraca wartość przypisaną/prawą stronę) Ten słownik jest tymczasowym lokalnym, który po prostu "znika w eterze". Wynik indeksu (lista słowników) jest tym, co na końcu znajduje się w głównym słowniku.

Jest to dziwny przypadek, do którego łatwiej wpaść dzięki użyciu obiektu jako typu wartości słownika.

Komentarze (0)