我想转换
var aList = new List<string>(new string[] { "elem1", "elem2", "elem3" });
初始化成
var aList = new List<string>() { "elem1", "elem2", "elem3" };
在我们的源代码中。我相信后者没有不必要的数组创建和数组 -> 列表转换。还是前者也有?或者编译器无论如何都会优化它?我以后可以面对任何不良副作用(或没有副作用)吗?
该项目使用 .NET 4。
我想转换
var aList = new List<string>(new string[] { "elem1", "elem2", "elem3" });
初始化成
var aList = new List<string>() { "elem1", "elem2", "elem3" };
在我们的源代码中。我相信后者没有不必要的数组创建和数组 -> 列表转换。还是前者也有?或者编译器无论如何都会优化它?我以后可以面对任何不良副作用(或没有副作用)吗?
该项目使用 .NET 4。
它们并不完全等价。
在第一种情况下,您正在创建一个新数组,然后将其传递给List<T>
构造函数,该构造函数将创建它自己的相同大小的内部数组,并调用源数组的CopyTo
方法将项目从源数组复制到它的内部数组中。
在第二种情况下,您List<T>
使用最初为空的数组(大小_defaultCapacity = 4
)构造一个新数组,然后调用 List 的Add
方法,这可能会导致内部数组在添加元素时被调整多次。
因此,在第一种情况下,您不必调整 List 的内部数组的大小,以及调用可能更有效的CopyTo
方法而不是 iterative Add
,但代价是必须一次在内存中创建两个数组。
这是您可以做的一件事,以避免创建两个数组并确保您没有调整列表的内部数组的大小:
var aList = new List<string>(3) { "elem1", "elem2", "elem3" };
由于魔法常数,我不一定会推荐这个用于生产代码,3
但话又说回来,无论如何你已经有了其他三个魔法常数。
如果转换后的代码如下所示:
var aList = new List<string>(3 /* !capacity specified */) { "elem1", "elem2", "elem3" };
它没有“不必要的数组创建”(如果您指定了多个 List<>::_defaultCapacity 项目)。
使用三个(或四个)字符串,您的代码也没有“不必要的数组创建”,因为 _defaultCapacity == 4。
换句话说,在第二个代码中(使用没有指定容量的集合初始化器)内部 List<> 的数组可以重新创建几次。
后者被编译成:
aList = new List<string();
aList.Add("elem1");
aList.Add("elem2");
aList.Add("elem3");
构造函数看起来正在做与此类似的事情(带有一些错误处理):
foreach(var t in items)
Add(t);
换句话说,数组创建是不必要的。对于微优化,最好按照您的建议进行优化。但是,实际上,您的结果不会有太大差异。