Reputation: 19841
I'm just thinking about the styling and performance. Previously I used to write something like,
var strings = new List<string> { "a", "b", "c" };
var ints = new List<int> { 1, 2, 3};
But now I tend to like this style more,
var strings = new [] { "a", "b", "c" }.ToList();
var ints = new [] { 1, 2, 3}.ToList();
I prefer the second style, but now considering - is it really worth to write it like that or maybe it's not that efficient and requires more operations?
Upvotes: 25
Views: 14690
Reputation: 70814
Example 1 (var ints = new List { 1, 2, 3};): Provides a 31.5% overhead (Eumerable.ToList) and List.Add() causes a 8.7% overhead.
Where as example 2: Causes a 11.8% overhead on List.ctor and a 5% for Ensure Capacity.
(Results from Red Gate ANTS Performance Profiler)
You can see that var ints = new List { 1, 2, 3}; has more operations to perform via the disassembly
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
}
Upvotes: 7
Reputation: 1995
I like the first versions. But regarding perfomance I think the best is to use the array and define specifically the number of elements is going to be if of course this can be possible:
var x = new int[3] { 1, 3, 3 }.ToList();
Upvotes: 1
Reputation: 30530
Setting aside the difference between the two from a performance perspective, the former expresses what you are trying to achieve in a better way.
Consider expressing the code in English:
declare a list of strings with these contents
And
declare an array of strings with these contents and then convert it into a list of strings
To me, the first seems more natural. Although I acknowledge the second may be better for you.
Upvotes: 13
Reputation: 1504122
I disagree with Darin: they're not equivalent in terms of performance. The latter version has to create a new array, and ToList
will then copy it into the new list. The collection initializer version is equivalent to:
var tmp = new List<int>();
tmp.Add(1);
tmp.Add(2);
tmp.Add(3);
var ints = tmp;
Assuming the list starts off with a large enough buffer, that won't require any further allocation - although it will involve a few method calls. If you do this for a very large number of items, then it will require more allocations than the ToList
version, because it will copy the items as it goes.
The performance difference is likely to be negligible, but it's non-zero (and not clearly better in either direction - there are fewer calls in the array version, but more allocation).
I would concentrate more on style than performance unless you have a reason to suspect that the difference is significant, in which case you should measure rather than just guessing.
Personally I prefer the first form - I think it makes it clearer that you're using a list right from the start. Another alternative would be to write your own static class:
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();
}
}
Then you can write:
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
This still makes it clear that you're using lists, but takes advantage of type inference.
You may well consider it overkill though :)
Upvotes: 42
Reputation: 133669
I guess in the first case elements are automatically added to the list while in the second one first an array is created then it is iterated and every element is added to the list.
While probably second one will be optimized to avoid a real array creation it is worth noticing that if this operation is done inside a loop you probably twice the object allocation amount (unless it's straightly optimized) with no real need to do that.
You should check bytecode to be sure of it.
I'm not fond of C# internals though so take this with care!
Upvotes: 6