C# 新[]或新列表<;T>;?

C# 新[]或新列表<;T>;?,c#,.net,performance,C#,.net,Performance,我只是在考虑款式和性能。以前我写过这样的东西 var strings = new List<string> { "a", "b", "c" }; var ints = new List<int> { 1, 2, 3}; 我更喜欢第二种风格,但现在考虑一下——这样写真的值得吗?或者它效率不高,需要更多的操作?我猜在第一种情况下,元素会自动添加到列表中,而在第二种情况下,首先创建一个数组,然后对其进行迭代,并将每个元素添加到列表中 虽然可能会对第二个进行优化,以避免真正的数

我只是在考虑款式和性能。以前我写过这样的东西

var strings = new List<string> { "a", "b", "c" };
var ints = new List<int> { 1, 2, 3};

我更喜欢第二种风格,但现在考虑一下——这样写真的值得吗?或者它效率不高,需要更多的操作?

我猜在第一种情况下,元素会自动添加到列表中,而在第二种情况下,首先创建一个数组,然后对其进行迭代,并将每个元素添加到列表中

虽然可能会对第二个进行优化,以避免真正的数组创建,但值得注意的是,如果在循环中执行此操作,则对象分配量可能会增加一倍(除非直接进行了优化),而无需执行此操作

你应该检查字节码以确定它


不过我不喜欢C#internal,所以要小心

从性能角度来看,撇开两者之间的差异不谈,前者表达了您试图以更好的方式实现的目标

考虑用英语表达代码:

声明包含这些内容的字符串列表

声明包含这些内容的字符串数组,然后将其转换为字符串列表


对我来说,第一个似乎更自然。尽管我承认第二种可能对你更有利。

我不同意达林的观点:它们在性能上并不等同。后一个版本必须创建一个新数组,然后
ToList
将其复制到新列表中。集合初始值设定项版本等效于:

var tmp = new List<int>();
tmp.Add(1);
tmp.Add(2);
tmp.Add(3);
var ints = tmp;
然后你可以写:

var ints = Lists.Of(1);
var ints = Lists.Of(1, 2, 3);
var ints = Lists.Of(1, 2, 3, 5, 6, 7, 8); // Use the params version
这仍然表明您使用的是列表,但利用了类型推断

>你可以很好的考虑:(

p>实例1)(var int =新列表{ 1, 2, 3 };):提供一个31.5%开销(EUMPLATE。TURIST)和列表。 其中,示例2:导致List.ctor的开销为11.8%,确保容量为5%

(来自红门蚂蚁性能分析器的结果)

您可以看到var ints=newlist{1,2,3};有更多的操作要通过拆解执行

 var intsx = new[] {1, 2, 3}.ToList();
0000003f  mov         edx,3 
00000044  mov         ecx,60854186h 
00000049  call        FFF5FD70 
0000004e  mov         dword ptr [ebp-4Ch],eax 
00000051  lea         ecx,[ebp-50h] 
00000054  mov         edx,872618h 
00000059  call        61490806 
0000005e  lea         eax,[ebp-50h] 
00000061  push        dword ptr [eax] 
00000063  mov         ecx,dword ptr [ebp-4Ch] 
00000066  call        614908E3 
0000006b  mov         ecx,dword ptr [ebp-4Ch] 
0000006e  call        dword ptr ds:[008726D8h] 
00000074  mov         dword ptr [ebp-54h],eax 
00000077  mov         eax,dword ptr [ebp-54h] 
0000007a  mov         dword ptr [ebp-40h],eax 

 var ints = new List<int> { 1, 2, 3 };
0000007d  mov         ecx,60B59894h 
00000082  call        FFF5FBE0 
00000087  mov         dword ptr [ebp-58h],eax 
0000008a  mov         ecx,dword ptr [ebp-58h] 
0000008d  call        60805DB0 
00000092  mov         eax,dword ptr [ebp-58h] 
00000095  mov         dword ptr [ebp-48h],eax 
00000098  mov         ecx,dword ptr [ebp-48h] 
0000009b  mov         edx,1 
000000a0  cmp         dword ptr [ecx],ecx 
000000a2  call        608070C0 
000000a7  nop 
000000a8  mov         ecx,dword ptr [ebp-48h] 
000000ab  mov         edx,2 
000000b0  cmp         dword ptr [ecx],ecx 
000000b2  call        608070C0 
000000b7  nop 
000000b8  mov         ecx,dword ptr [ebp-48h] 
000000bb  mov         edx,3 
000000c0  cmp         dword ptr [ecx],ecx 
000000c2  call        608070C0 
000000c7  nop 
000000c8  mov         eax,dword ptr [ebp-48h] 
000000cb  mov         dword ptr [ebp-44h],eax 
        }
var intsx=new[]{1,2,3}.ToList();
000000 3F mov edx,3
000000 44 mov ecx,60854186h
000000 49呼叫FFF5FD70
0000004e mov dword ptr[ebp-4Ch],eax
00000051 lea ecx,[ebp-50h]
00000054 mov edx,872618小时
00000059拨打61490806
000000 5e lea eax,[ebp-50h]
00000061推送dword ptr[eax]
000000 63 mov ecx,德沃德ptr[ebp-4Ch]
00000066拨打614908E3
0000006b mov ecx,德沃德ptr[ebp-4Ch]
0000006e呼叫dword ptr ds:[008726D8h]
000000 74 mov德沃德ptr[ebp-54h],eax
00000077 mov eax,德沃德ptr[ebp-54h]
000000 7A mov dword ptr[ebp-40h],eax
var ints=新列表{1,2,3};
000000 7D mov ecx,60B59894h
000000 82呼叫FFF5FBE0
00000087 mov德沃德ptr[ebp-58h],eax
0000008a mov ecx,德沃德ptr[ebp-58h]
000000 8D呼叫60805DB0
000000 92 mov eax,dword ptr[ebp-58h]
000000 95 mov德沃德ptr[ebp-48h],eax
000000 98 mov ecx,德沃德ptr[ebp-48h]
000000 9B mov edx,1
000000 A0 cmp dword ptr[ecx],ecx
000000 A2呼叫608070C0
000000 A7无
000000 A8 mov ecx,德沃德ptr[ebp-48h]
000000 AB mov edx,2
000000 B0 cmp dword ptr[ecx],ecx
000000 B2呼叫608070C0
000000 B7 nop
000000 B8 mov ecx,德沃德ptr[ebp-48h]
000000 bb mov edx,3
000000 C0 cmp dword ptr[ecx],ecx
000000 C2呼叫608070C0
000000 C7 nop
000000 C8 mov eax,dword ptr[ebp-48h]
000000 CB mov dword ptr[ebp-44h],eax
}

我喜欢第一个版本。但关于性能,我认为最好是使用数组,并明确定义元素的数量,当然,如果可能的话:

var x = new int[3] { 1, 3, 3 }.ToList();

你为什么喜欢第二种风格?我认为它的可读性较差,尤其是在使用
var
时。您对它进行过性能测试吗?只要计时并做100次,就可以看到测试中的平均值。我更喜欢第一个版本,因为我发现它更容易为人类阅读。我认为这只是一个观点问题,有些人喜欢洋葱,有些人讨厌洋葱。最好的办法是选择一个并坚持下去(如果有的话,在整个团队中强制执行)@alexanderb根据我的评测测试,我已经在我的答案中包括了开销,这表明哪个更快。这正是我在阅读你的答案前一秒钟所想的:)1+。这就是我想说的!大量的数组复制正在发生,而且它不是免费的。当然,它不会创建两倍于所需的项,也不会执行其他操作。事实上,这种差异非常微小,在初始化列表一次时就不用担心了,但是如果多次实例化列表,它们会随着时间的推移而不同。但我们讨论的是任何情况下的微小差异。如果我很好地理解,他的意思是,当源数据不是很大时,第一个版本的性能更好,因为重新分配(新分配是两倍大+复制数据)@alexanderb:不一定-集合初始值设定项版本中涉及的分配和复制更少(对于少量元素),但对
Add
的调用更多,每个调用都必须检查是否需要扩展,等等。这些
call
s做什么?它们的成本是多少?我没有安装任何分析工具来提供准确的成本,这是反汇编的原始输出,显示对问题中的两个示例执行了多少操作。将安装和编辑。@L.B更新了我的答案,以提供您所需的成本。我认为显式指定数组大小不会增加任何内容。编译器可以通过静态分析确定它;并且将以构造函数喜欢的任何大小创建
列表
 var intsx = new[] {1, 2, 3}.ToList();
0000003f  mov         edx,3 
00000044  mov         ecx,60854186h 
00000049  call        FFF5FD70 
0000004e  mov         dword ptr [ebp-4Ch],eax 
00000051  lea         ecx,[ebp-50h] 
00000054  mov         edx,872618h 
00000059  call        61490806 
0000005e  lea         eax,[ebp-50h] 
00000061  push        dword ptr [eax] 
00000063  mov         ecx,dword ptr [ebp-4Ch] 
00000066  call        614908E3 
0000006b  mov         ecx,dword ptr [ebp-4Ch] 
0000006e  call        dword ptr ds:[008726D8h] 
00000074  mov         dword ptr [ebp-54h],eax 
00000077  mov         eax,dword ptr [ebp-54h] 
0000007a  mov         dword ptr [ebp-40h],eax 

 var ints = new List<int> { 1, 2, 3 };
0000007d  mov         ecx,60B59894h 
00000082  call        FFF5FBE0 
00000087  mov         dword ptr [ebp-58h],eax 
0000008a  mov         ecx,dword ptr [ebp-58h] 
0000008d  call        60805DB0 
00000092  mov         eax,dword ptr [ebp-58h] 
00000095  mov         dword ptr [ebp-48h],eax 
00000098  mov         ecx,dword ptr [ebp-48h] 
0000009b  mov         edx,1 
000000a0  cmp         dword ptr [ecx],ecx 
000000a2  call        608070C0 
000000a7  nop 
000000a8  mov         ecx,dword ptr [ebp-48h] 
000000ab  mov         edx,2 
000000b0  cmp         dword ptr [ecx],ecx 
000000b2  call        608070C0 
000000b7  nop 
000000b8  mov         ecx,dword ptr [ebp-48h] 
000000bb  mov         edx,3 
000000c0  cmp         dword ptr [ecx],ecx 
000000c2  call        608070C0 
000000c7  nop 
000000c8  mov         eax,dword ptr [ebp-48h] 
000000cb  mov         dword ptr [ebp-44h],eax 
        }
var x = new int[3] { 1, 3, 3 }.ToList();