这个 C# 字典初始化如何正确?
How is this C# dictionary initialization correct?
我偶然发现了以下内容,我想知道为什么它没有引发语法错误。
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
}
}
};
请注意 "MyA" 和 "OtherAs" 之间缺少“,”。
这是混淆发生的地方:
- 代码编译。
- 最终的字典"dict"只包含三个元素:"Id"、"Tribes"和"MyA"。
- 除了 "MyA" 之外的所有值都是正确的,
- "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
是 "Name" 和 "Points" 的字典,用 "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
}
}
)
)
这里发生的事情是您正在创建一个字典然后索引到它。然后返回 indexer/assignment 表达式的结果,这就是分配到 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
返回给第二个字典的索引器赋值的结果(赋值returns 值assigned/right 手边)那个字典是一个临时本地,只是"disappears into the ether"。索引器的结果(字典列表)就是最后放入主字典的内容。
这是一个奇怪的情况,由于使用 object
作为字典值的类型,因此更容易陷入这种情况。
我偶然发现了以下内容,我想知道为什么它没有引发语法错误。
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
}
}
};
请注意 "MyA" 和 "OtherAs" 之间缺少“,”。
这是混淆发生的地方:
- 代码编译。
- 最终的字典"dict"只包含三个元素:"Id"、"Tribes"和"MyA"。
- 除了 "MyA" 之外的所有值都是正确的,
- "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
是 "Name" 和 "Points" 的字典,用 "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
}
}
)
)
这里发生的事情是您正在创建一个字典然后索引到它。然后返回 indexer/assignment 表达式的结果,这就是分配到 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
返回给第二个字典的索引器赋值的结果(赋值returns 值assigned/right 手边)那个字典是一个临时本地,只是"disappears into the ether"。索引器的结果(字典列表)就是最后放入主字典的内容。
这是一个奇怪的情况,由于使用 object
作为字典值的类型,因此更容易陷入这种情况。