这个 C# 字典初始化如何正确?

Dan*_*tte 64 c# dictionary initialization

我偶然发现了以下内容,我想知道为什么它没有引发语法错误。

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
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意,“MyA”和“OtherAs”之间缺少“,”。

这就是混乱发生的地方:

  1. 代码编译。
  2. 最终字典“dict”仅包含三个元素:“Id”、“Tribes”和“MyA”。
  3. 除了“MyA”之外的所有值都是正确的,
  4. “MyA”采用“OtherAs”的声明值,而忽略其原始值。

为什么这不违法?这是故意的吗?

Swe*_*per 55

缺少的逗号使一切变得不同。它导致索引器["OtherAs"]应用于此字典:

new Dictionary<string, object>
{
    ["Name"] = "Solo",
    ["Points"] = 88
}
Run Code Online (Sandbox Code Playgroud)

所以基本上你是说:

new Dictionary<string, object>
{
    ["Name"] = "Solo",
    ["Points"] = 88
}["OtherAs"] = new List<Dictionary<string, object>>
{
    new Dictionary<string, object>
    {
        ["Points"] = 1999
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意,这是一个赋值表达式 ( 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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是您的代码,但已重新格式化并添加了一些括号以说明编译器如何解析它:

["MyA"] 
= 
(
    (
        new Dictionary<string, object>
        {
            ["Name"] = "Solo",
            ["Points"] = 88
        }["OtherAs"] 
    )
    = 
    (
        new List<Dictionary<string, object>>
        {
            new Dictionary<string, object>
            {
                ["Points"] = 1999
            }
        }
    )
)
Run Code Online (Sandbox Code Playgroud)


pin*_*x33 20

这里发生的事情是您正在创建一个字典,然后对其进行索引。然后返回索引器/分配表达式的结果,这就是分配到MyA字典槽中的内容。

这个:

["MyA"] = new Dictionary<string, string> 
{
   ["Name"] = "Solo",
   ["Points"] = "88" 
}
["OtherAs"] = new List<Dictionary<string, object>>
{
   new Dictionary<string, object>
   {
       ["Points"] = 1999
   }
}
Run Code Online (Sandbox Code Playgroud)

可以拆分为以下伪代码:

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
Run Code Online (Sandbox Code Playgroud)

返回分配给第二个字典的索引器的结果(分配返回分配的值/右侧)该字典是一个临时本地,只是“消失在以太中”。索引器的结果(字典列表)是最后放入主字典的内容。

这是一个奇怪的情况,由于使用objectas 字典值的类型,更容易陷入这种情况。