在字典初始化程序中,有两种创建带有内容的字典的方法:
new Dictionary<string, GradientSpace>
{
["userSpaceOnUse"] = GradientSpace.Absolute,
["objectBoundingBox"] = GradientSpace.Relative
})
和
new Dictionary<string, GradientSpace>
{
{"userSpaceOnUse", GradientSpace.Absolute},
{"objectBoundingBox", GradientSpace.Relative}
});
这两种语法有什么区别吗?还是只是偏爱问题?
答案 0 :(得分:6)
当源如下并且目标框架是.NET 4.7.1时:
var x = new Dictionary<string, int>
{
["userSpaceOnUse"] = 1,
["objectBoundingBox"] = 3
};
var y = new Dictionary<string, int> {
{"userSpaceOnUse", 1},
{"objectBoundingBox", 3}
};
这将导致以下中间语言(使用JetBrains dotPeek):
// [18 13 - 22 15]
IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::.ctor()
IL_0006: dup
IL_0007: ldstr "userSpaceOnUse"
IL_000c: ldc.i4.1
IL_000d: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::set_Item(!0/*string*/, !1/*int32*/)
IL_0012: nop
IL_0013: dup
IL_0014: ldstr "objectBoundingBox"
IL_0019: ldc.i4.3
IL_001a: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::set_Item(!0/*string*/, !1/*int32*/)
IL_001f: nop
IL_0020: stloc.0 // x
// [25 13 - 28 15]
IL_0021: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::.ctor()
IL_0026: dup
IL_0027: ldstr "userSpaceOnUse"
IL_002c: ldc.i4.1
IL_002d: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0/*string*/, !1/*int32*/)
IL_0032: nop
IL_0033: dup
IL_0034: ldstr "objectBoundingBox"
IL_0039: ldc.i4.3
IL_003a: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0/*string*/, !1/*int32*/)
IL_003f: nop
IL_0040: stloc.1 // y
第一种方法导致设置索引器/属性,而第二种方法使用Add()方法,这意味着它们的翻译方式有所不同。
在这种情况下,Dictionarry类的.NET Core源代码也很有趣: https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/collections/generic/dictionary.cs
答案 1 :(得分:1)
使用[ … ] = …
的(较新的)语法才能使用索引器的set
访问器,因此您具有:
tmpDict["userSpaceOnUse"] = GradientSpace.Absolute;
tmpDict["objectBoundingBox"] = GradientSpace.Relative;
而其他语法则需要使用名称为Add
的合适方法,因此:
tmpDict.Add("userSpaceOnUse", GradientSpace.Absolute);
tmpDict.Add("objectBoundingBox, GradientSpace.Relative);
这种差异不是C#编译器的任意选择; C#语言规范要求它。
对于特定的类型System.Collections.Generic.Dictionary<,>
,当密钥已经存在时,两个成员之间是有区别的(索引器设置器与Add
方法)。因此,如果您(大概)不小心两次输入了相同的密钥,如下所示:
new Dictionary<string, GradientSpace>
{
["userSpaceOnUse"] = GradientSpace.Absolute,
["objectBoundingBox"] = GradientSpace.Relative,
["userSpaceOnUse"] = GradientSpace.Relative,
}
分别:
new Dictionary<string, GradientSpace>
{
{ "userSpaceOnUse", GradientSpace.Absolute },
{ "objectBoundingBox", GradientSpace.Relative },
{ "userSpaceOnUse", GradientSpace.Relative },
}
您会感到与众不同!在第一种情况下,最后一次使用键"userSpaceOnUse"
只会覆盖第一个值(带有"userSpaceOnUse"
的第一行变得无关紧要),而在最后一种情况下,它将用{{1} }。