var maxDictionary = new Dictionary<int, double> { { 10, 40000 } };
在上面的代码中,编译器是否使用构造函数?或者编译器是否创建了KeyValuePair并添加到字典中?我试图理解编译器如何解释它。
答案 0 :(得分:19)
是的,编译器使用默认的无参数构造函数,然后通过Dictionary.Add方法添加集合初始化程序中指定的所有值。正如Jon指出的那样,你的代码被编译成
Dictionary<int, double> maxDictionary2;
Dictionary<int, double> maxDictionary;
maxDictionary2 = new Dictionary<int, double>();
maxDictionary2.Add(10, 40000.0);
maxDictionary = maxDictionary2;
生成IL:
.maxstack 3
.locals init (
[0] class [mscorlib]Dictionary`2<int32, float64> maxDictionary,
[1] class [mscorlib]Dictionary`2<int32, float64> maxDictionary2)
L_0000: nop
L_0001: newobj instance void [mscorlib]Dictionary`2<int32, float64>::.ctor()
L_0006: stloc.1
L_0007: ldloc.1
L_0008: ldc.i4.s 10
L_000a: ldc.r8 40000
L_0013: callvirt instance void [mscorlib]Dictionary`2<int32, float64>::Add(!0, !1)
L_0018: nop
L_0019: ldloc.1
L_001a: stloc.0
即。创建分配给临时变量maxDictionary2
的字典,填充值,然后只有对创建和填充字典的引用才会复制到maxDictionary
变量。
请记住,如果您不想使用parammeterless,可以指定任何其他构造函数。例如。你可以使用一个设置初始容量:
var maxDictionary = new Dictionary<int, double>(10) { { 10, 40000 } };
答案 1 :(得分:7)
var maxDictionary = new Dictionary<int, double> { { 10, 40000 } };
以下是程序生成的IL
IL_0001: newobj System.Collections.Generic.Dictionary<System.Int32,System.Double>..ctor
IL_0006: stloc.1 // <>g__initLocal0
IL_0007: ldloc.1 // <>g__initLocal0
IL_0008: ldc.i4.s 0A
IL_000A: ldc.r8 00 00 00 00 00 88 E3 40
IL_0013: callvirt System.Collections.Generic.Dictionary<System.Int32,System.Double>.Add
IL_0018: nop
IL_0019: ldloc.1 // <>g__initLocal0
IL_001A: stloc.0 // maxDictionary
显然,它使用无参数构造函数并调用Add
方法。标签“IL_0013”显示对Add
方法的调用
等效的c#代码将是
Dictionary<int, double> maxDictionary;
Dictionary<int, double> temp = new Dictionary<int, double>();
temp.Add(10, 40000.0);
maxDictionary = temp;
值得注意的是编译器使用temp
变量,我可以看到两个原因
答案 2 :(得分:1)
其他人已经指出如何 C#编译器如何发出对Add
的{{1}}方法的调用。但是,还没有人谈论何时 C#编译器发出这些调用。
好吧,它与Dictionary
(或System.Collections.Dictionary
)类无关。此功能称为集合初始化,因为它要求目标实例具有实现System.Collections.Generic.Dictionary<TKey, TValue>
接口的类型。唯一的要求是存在名为System.Collections.IEnumerable
的方法,甚至不会考虑其签名或返回类型。
当Add
方法只需要一个参数时,初始化看起来像这样:
Add
上面的代码完全表示class Foo : IEnumerable
{
public void Add(string a)
{
}
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
var myFoo = new Foo
{
"item 1",
"item 2",
"item 3",
"item 4",
"item 5"
};
(或System.Collections.List
)类在实现System.Collections.Generic.List<T>
时发生的情况。
当System.Collections.IEnumerable
方法需要两个或更多参数时(例如,对于字典而言),则每个项目都必须具有该方法的每个参数的值,因此它被设计为在括号内包含这些值,并且看起来像这个:
Add
对于好奇的人:
此答案中的代码包含与圈子有关的有趣的事情。有人会发现吗?