16

在集合类型上使用大括号初始值设定项是否设置了它的容量,还是仍然需要指定它?

也就是说,是否:

var list = new List<string>(){ "One", "Two" };

结果与此相同:

var list = new List<string>(2){ "One", "Two" };
4

4 回答 4

14

对象初始化器只是为每个项目调用Add

var list = new List<string>{ "One", "Two", "Three" };

如您所见,在这种情况下,无参数构造函数被调用:

L_0000: nop 
L_0001: newobj instance void [mscorlib]System.Collections.Generic.List`1<string>::.ctor()
L_0006: stloc.1 
L_0007: ldloc.1 
L_0008: ldstr "One"
L_000d: callvirt instance void [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
L_0012: nop 
L_0013: ldloc.1 
L_0014: ldstr "Two"
L_0019: callvirt instance void [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
L_001e: nop 
L_001f: ldloc.1 
L_0020: ldstr "Three"
L_0025: callvirt instance void [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
L_002a: nop 
L_002b: ldloc.1 

因此,您应该手动设置容量:

var list = new List<string>(5){ "One", "Two", "Three" };

编译成:

L_0000: nop 
L_0001: ldc.i4.5 
L_0002: newobj instance void [mscorlib]System.Collections.Generic.List`1<string>::.ctor(int32)
// rest is same

因此,算法非常明显 - 它调用您指定的构造函数(默认情况下无参数),然后调用Add每个项目。

注意:我知道,默认容量是 4,List<T>并且我验证了如果我们在初始化程序中传递超过 4 个项目会发生什么(例如,编译器可能根据项目数确定要调用哪个构造函数)但结果是相同的 - 默认情况下调用无参数构造函数.

我认为集合初始化器的目的是创建小型集合(1 - 8 个项目),因此会对性能产生一点影响(如果您将 8 个项目传递给初始化器,则只有一次调整大小)。没有人期望您会使用 100 个项目的就地初始化。如果你打算这样做,你应该使用适当的集合构造函数。

于 2013-09-24T07:37:16.167 回答
3

集合初始化器使用可用的Add方法将项目添加到集合中。因此,行为将与使用空构造函数调用该Add方法相同。

实际上,编译器会将您的对象初始值设定项语法更改为对该Add方法的调用。所以,是否使用对象初始化器是无关紧要的。重要的是您是否决定使用构造函数重载以及实际添加的项目数量。

于 2013-09-24T07:30:50.497 回答
1

使用无参数构造函数初始化 List 后,内部数组设置为长度为 0 的数组。

当调用 Add()、Insert() 或 InsertRange() 时,重新计算列表的容量:

  • 如果列表中没有其他元素,则容量设置为 4(默认容量)。
  • 如果还有其他元素,则容量设置为元素数量的两倍。

如果您指定容量,则以该大小创建内部数组。

参考:DotNet 来源:RefSrc\Source.NET 4.5\4.5.50709.0\net\ndp\clr\src\BCL\System\Collections\Generic\List.cs\597531\List.cs

于 2013-09-24T07:41:51.077 回答
0

根据文档并考虑到对象初始化器的计数为 2,它最终也会设置容量。

容量总是大于等于 Count

于 2013-09-24T07:32:33.863 回答