新[]或新列表<T>?

Ale*_*sky 25 .net c# performance

我只是想着造型和性能.以前我曾经写过类似的东西,

var strings = new List<string> { "a", "b", "c" };
var ints = new List<int> { 1, 2, 3};
Run Code Online (Sandbox Code Playgroud)

但现在我更倾向于喜欢这种风格,

var strings = new [] { "a", "b", "c" }.ToList();
var ints = new [] { 1, 2, 3}.ToList();
Run Code Online (Sandbox Code Playgroud)

我更喜欢第二种风格,但现在正在考虑 - 是否真的值得这样写它或者它不是那么有效并且需要更多操作?

Jon*_*eet 42

我不同意达林:他们在表现上并不相同.后一版本必须创建一个新数组,然后ToList将其复制到新列表中.集合初始化程序版本相当于:

var tmp = new List<int>();
tmp.Add(1);
tmp.Add(2);
tmp.Add(3);
var ints = tmp;
Run Code Online (Sandbox Code Playgroud)

虽然它-假设列表,并附有足够大的缓冲,这将不需要任何进一步的分配开始了涉及几个方法调用.如果对大量项目执行此操作,则需要比版本更多的分配ToList,因为它将按原样复制项目.

性能差异可能是微不足道的,但它是非零的(而不是明确地在两个方向上更好的-有在阵列版本呼叫减少,但更多的分配).

我会更专注于风格而不是表现,除非你有理由怀疑差异是显着的,在这种情况下你应该衡量而不仅仅是猜测.

就个人而言,我更喜欢第一种形式 - 我认为从一开始就使用列表就更清楚了.另一种方法是编写自己的静态类:

public static class Lists
{
    public static List<T> Of<T>(T item0)
    {
        return new List<T> { item0 };
    }

    public static List<T> Of<T>(T item0, T item1)
    {
        return new List<T> { item0, item1 };
    }

    public static List<T> Of<T>(T item0, T item1, T item2)
    {
        return new List<T> { item0, item1, item2 };
    }

    ... as many times as you really care about, then ...

    public static List<T> Of<T>(params T[] items)
    {
        return items.ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以写:

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
Run Code Online (Sandbox Code Playgroud)

这仍然清楚表明您正在使用列表,但利用类型推断.

你可能会认为它有点过分但:)


Jam*_*man 13

从绩效的角度来看两者之间的差异,前者表达了你想要以更好的方式实现的目标.

考虑用英语表达代码:

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

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

对我来说,第一个似乎更自然.虽然我承认第二个可能对你更好.


Dar*_*ren 7

示例1(var ints = new List {1,2,3};):提供31.5%的开销(Eumerable.ToList),List.Add()导致8.7%的开销.

例如2:在List.ctor上产生11.8%的开销,在Ensure Capacity上产生5%的开销.

(Red Gate ANTS Performance Profiler的结果)

你可以看到var ints = new List {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 
        }
Run Code Online (Sandbox Code Playgroud)

  • 这些`叫做什么?他们的成本是多少? (3认同)

Jac*_*ack 6

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

虽然可能第二个将被优化以避免真正的阵列创建,但值得注意的是,如果此操作在循环内完成,则可能是对象分配量的两倍(除非它是直接优化的),而没有真正需要这样做.

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

我不喜欢C#内部,所以请小心谨慎!