Я наткнулся на следующее, и мне интересно, почему это не вызвало ошибку синтаксиса.
var dict = new Dictionary<string, object>
{
["Id"] = Guid.NewGuid(),
["Племена"] = new List<int> { 4, 5 },
["MyA"] = new Dictionary<string, object>
{
["Имя"] = "Соло",
["Очки"] = 88
}
["OtherAs"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Точки"] = 1999 г.
}
}
};
Обратите внимание, что "," отсутствует между "MyA" и "OtherAs".
Именно здесь и происходит путаница:
Почему это не является незаконным? Так задумано?
Пропущенная запятая делает всю разницу. Она заставляет индексатор ["OtherAs"]
быть примененным к этому словарю:
new Dictionary<string, object>
{
["Name"] = "Solo",
["Points"] = 88
}
То есть, по сути, вы говорите:
new Dictionary<string, object>
{
["Name"] = "Solo",
["Points"] = 88
}["OtherAs"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Points"] = 1999
}
};
Обратите внимание, что это выражение присваивания (x = y
). Здесь x
- это словарь с "Именем" и "Точками", индексированный с помощью "OtherAs"
, а y
- это List<Dictionary<string, object>>
. Выражение присваивания оценивается в присваиваемое значение (y
), которое является списком словарей.
Результат всего выражения присваивается ключу "MyA", поэтому "MyA" имеет список словарей.
Вы можете убедиться, что все происходит именно так, изменив тип словаря 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
}
}
Вот ваш код, но переформатированный и с добавлением некоторых скобок, чтобы проиллюстрировать, как компилятор разобрал его:
["MyA"]
=
(
(
new Dictionary<string, object>
{
["Name"] = "Solo",
["Points"] = 88
}["OtherAs"]
)
=
(
new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Points"] = 1999
}
}
)
)
Здесь происходит то, что вы создаете словарь, а затем индексируете его. Затем возвращается результат выражения индексации/присвоения, который и присваивается в слот словаря MyA
.
Это:
["MyA"] = new Dictionary<string, string>
{
["Name"] = "Solo",
["Points"] = "88"
}
["OtherAs"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Points"] = 1999
}
}
Можно разделить на следующие псевдокоды:
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
Возвращается результат присвоения индексатору второго словаря (присвоение возвращает присвоенное значение/правую часть) Этот словарь является временным локальным, который просто "исчезает в эфире". Результат работы индексатора (список словарей) - это то, что в итоге помещается в основной словарь.
Это странный случай, в который легче попасть из-за использования object
в качестве типа значений словаря.