2

我想转换

var aList = new List<string>(new string[] { "elem1", "elem2", "elem3" });

初始化成

var aList = new List<string>() { "elem1", "elem2", "elem3" };

在我们的源代码中。我相信后者没有不必要的数组创建和数组 -> 列表转换。还是前者也有?或者编译器无论如何都会优化它?我以后可以面对任何不良副作用(或没有副作用)吗?

该项目使用 .NET 4。

4

3 回答 3

4

它们并不完全等价。

  1. 在第一种情况下,您正在创建一个新数组,然后将其传递给List<T>构造函数,该构造函数将创建它自己的相同大小的内部数组,并调用源数组的CopyTo方法将项目从源数组复制到它的内部数组中。

  2. 在第二种情况下,您List<T>使用最初为空的数组(大小_defaultCapacity = 4)构造一个新数组,然后调用 List 的Add方法,这可能会导致内部数组在添加元素时被调整多次。

因此,在第一种情况下,您不必调整 List 的内部数组的大小,以及调用可能更有效的CopyTo方法而不是 iterative Add,但代价是必须一次在内存中创建两个数组。

这是您可以做的一件事,以避免创建两个数组确保您没有调整列表的内部数组的大小:

var aList = new List<string>(3) { "elem1", "elem2", "elem3" };

由于魔法常数,我不一定会推荐这个用于生产代码,3但话又说回来,无论如何你已经有了其他三个魔法常数。

于 2013-06-24T21:00:09.780 回答
1

如果转换后的代码如下所示:

var aList = new List<string>(3 /* !capacity specified */) { "elem1", "elem2", "elem3" };

它没有“不必要的数组创建”(如果您指定了多个 List<>::_defaultCapacity 项目)。

使用三个(或四个)字符串,您的代码也没有“不必要的数组创建”,因为 _defaultCapacity == 4。

换句话说,在第二个代码中(使用没有指定容量的集合初始化器)内部 List<> 的数组可以重新创建几次。

于 2013-06-24T21:04:01.940 回答
1

后者被编译成:

aList = new List<string();
aList.Add("elem1");
aList.Add("elem2");
aList.Add("elem3");

构造函数看起来正在做与此类似的事情(带有一些错误处理):

foreach(var t in items)
    Add(t);

换句话说,数组创建是不必要的。对于微优化,最好按照您的建议进行优化。但是,实际上,您的结果不会有太大差异。

于 2013-06-24T20:50:50.457 回答