Mi sono imbattuto nel seguente e mi sto chiedendo perché non ha sollevato un errore di sintassi.
var dict = new Dictionary<string, object>
{
["Id"] = Guid.NewGuid(),
["Tribù"] = new List<int> { 4, 5 },
["MyA"] = new Dictionary<string, object>
{
["Nome"] = "Solo",
["Punti"] = 88
}
["OtherAs"] = new List<Dictionary<string, object>;
{
new Dictionary<string, object>
{
["Punti"] = 1999
}
}
};
Notate che la "," manca tra la "MyA", e la "OtherAs".
È qui che avviene la confusione:
Perché questo non è illegale? È stato progettato così?
La virgola mancante fa la differenza. Fa sì che l'indicizzatore ["OtherAs"]
venga applicato a questo dizionario:
new Dictionary<string, object>
{
["Name"] = "Solo",
["Points"] = 88
}
Quindi essenzialmente stai dicendo:
new Dictionary<string, object>
{
["Name"] = "Solo",
["Points"] = 88
}["OtherAs"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Points"] = 1999
}
};
Nota che questa è un'espressione di assegnazione (x = y
). Qui x
è il dizionario con "Name" e "Points", indicizzato con "OtherAs"
e y
è la List<Dictionary<string, object>
. Un'espressione di assegnazione valuta il valore da assegnare (y
), che è la lista di dizionari.
Il risultato dell'intera espressione viene quindi assegnato alla chiave "MyA", che è il motivo per cui "MyA" ha la lista di dizionari.
Puoi confermare che questo è ciò che sta accadendo cambiando il tipo del dizionario 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
}
}
Ecco il tuo codice, ma riformattato e alcune parentesi aggiunte per illustrare come il compilatore lo ha analizzato:
["MyA"]
=
(
(
new Dictionary<string, object>
{
["Name"] = "Solo",
["Points"] = 88
}["OtherAs"]
)
=
(
new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Points"] = 1999
}
}
)
)
Quello che sta succedendo qui è che stai creando un dizionario e poi indicizzando in esso. Il risultato dell'espressione di indicizzazione/assegnazione viene quindi restituito e questo è ciò che viene assegnato allo slot del dizionario MyA
.
Questo:
["MyA"] = new Dictionary<string, string>
{
["Name"] = "Solo",
["Points"] = "88"
}
["OtherAs"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Points"] = 1999
}
}
Può essere suddiviso nel seguente psuedo-codice:
var temp = new Dictionary<string, object>
{
["Name"] = "Solo",
["Points"] = 88
};
// indexed contains result of assignment
var indexed = temp["OtherAs"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Points"] = 1999
}
};
// value is set to result of assignment from previous step
["MyA"] = indexed;
// temp is discarded
Il risultato dell'assegnazione all'indicizzatore del secondo dizionario viene restituito (l'assegnazione restituisce il valore assegnato/lato destro) Quel dizionario è un locale temporaneo che semplicemente "scompare nell'etere". Il risultato dell'indicizzatore (la lista dei dizionari) è ciò che alla fine viene messo nel dizionario principale.
Questo è un caso strano, in cui è più facile cadere a causa dell'uso di object
come tipo dei valori del dizionario.