以下のようなものを偶然見つけたのですが、なぜシンタックスエラーにならなかったのか不思議です'。
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>>
{
新しいDictionary<string, object>
{
["Points"] = 1999
}
}
};
注意していただきたいのは、"MyA"と"OtherAs"の間に、"、"がないことです。
これが混乱の原因です。
1.コードはコンパイルされます。 2.最終的な辞書 "dict"には、"Id"、"Tribes"、および "MyA"の3つの要素しか含まれていません。 3.3. "MyA"を除くすべての要素の値は正しいです。 4. "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
}
}
)
)
ここで起こっていることは、辞書を作成して、それにインデックスを作成しているということです。その後、インデクサ/割り当て式の結果が返され、それが MyA
辞書スロットに割り当てられています。
これは
["MyA"] = new Dictionary<string, string>
{
["Name"] = "Solo",
["Points"] = "88"
}
["OtherAs"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["Points"] = 1999
}
}
以下のpsuedo-codeに分割することができます。
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
2番目の辞書のインデクサーに代入した結果が返ってきます(代入は代入された値を返します/右手)その辞書は、ただ"in the ether"に消えていく一時的なローカルです。インデクサーの結果(辞書のリスト)は、最終的にメインの辞書に入れられるものです。
これは奇妙なケースですが、辞書の値の型として object
を使用しているため、陥りやすくなっています。