.NET提供了一个通用列表容器,其性能几乎相同(请参阅阵列性能与列表问题).但是它们在初始化方面完全不同.
使用默认值很容易初始化数组,根据定义,它们已经具有一定的大小:
string[] Ar = new string[10];
这允许人们安全地分配随机项目,比如说:
Ar[5]="hello";
列表事情更棘手.我可以看到两种方法进行相同的初始化,这两种方式都不是你所谓的优雅:
ListL = new List (10); for (int i=0;i<10;i++) L.Add(null);
要么
string[] Ar = new string[10]; ListL = new List (Ar);
什么是更干净的方式?
编辑:到目前为止的答案是指容量,这不是预先填充列表.例如,在刚创建的容量为10的列表中,无法做到L[2]="somevalue"
编辑2:人们想知道为什么我想以这种方式使用列表,因为它不是他们打算使用的方式.我可以看到两个原因:
人们可以非常有说服力地认为列表是"下一代"阵列,增加灵活性几乎不会受到惩罚.因此,默认情况下应该使用它们.我指出它们可能不那么容易初始化.
我目前正在编写的是一个基类,它提供默认功能作为更大框架的一部分.在我提供的默认功能中,List的大小在高级中是已知的,因此我可以使用数组.但是,我想为任何基类提供动态扩展它的机会,因此我选择了一个列表.
小智.. 115
ListL = new List ( new string[10] );
+1:刚刚遇到一个情况,我需要一个可变大小的列表,在通过索引填充之前用一组固定的空值进行初始化(然后添加额外的数据,因此数组不合适).这个答案得到了实际和简单的投票. (4认同)
我个人认为这是最干净的方式 - 虽然在问题机构中提到它可能是笨拙的 - 不知道为什么 (3认同)
@RBT这是此方法的唯一缺点:*不会*重复使用该数组,因此您将立即拥有该数组的两个副本(如您所知,List在内部使用数组)。在极少数情况下,如果元素数量过多或存在内存限制,则可能会出现问题。是的,一旦List构造函数完成,多余的数组将有资格进行垃圾回收(否则将造成严重的内存泄漏)。请注意,符合条件并不意味着“立即收集”,而是下次运行垃圾收集时。 (2认同)
此答案分配10个新字符串-然后遍历它们,并根据需要将其复制。如果您正在使用大型阵列;那么甚至不要考虑这一点,因为它需要的内存是接受的答案的两倍。 (2认同)
Jon Skeet.. 72
我不能说我经常需要这个 - 你能否详细说明你为什么要这样做?我可能会把它作为一个静态方法放在一个帮助器类中:
public static class Lists { public static ListRepeatedDefault (int count) { return Repeated(default(T), count); } public static List Repeated (T value, int count) { List ret = new List (count); ret.AddRange(Enumerable.Repeat(value, count)); return ret; } }
您可以使用,Enumerable.Repeat(default(T), count).ToList()
但由于缓冲区大小调整,这将是低效的.
编辑:如评论中所述,如果您愿意,可以T
使用循环填充列表.那也会稍快一些.就个人而言,我发现代码使用count
更具描述性,并怀疑在现实世界中性能差异是无关紧要的,但您的里程可能会有所不同.
ListL = new List ( new string[10] );
我不能说我经常需要这个 - 你能否详细说明你为什么要这样做?我可能会把它作为一个静态方法放在一个帮助器类中:
public static class Lists { public static ListRepeatedDefault (int count) { return Repeated(default(T), count); } public static List Repeated (T value, int count) { List ret = new List (count); ret.AddRange(Enumerable.Repeat(value, count)); return ret; } }
您可以使用,Enumerable.Repeat(default(T), count).ToList()
但由于缓冲区大小调整,这将是低效的.
编辑:如评论中所述,如果您愿意,可以T
使用循环填充列表.那也会稍快一些.就个人而言,我发现代码使用count
更具描述性,并怀疑在现实世界中性能差异是无关紧要的,但您的里程可能会有所不同.
使用以int("capacity")作为参数的构造函数:
List= new List (10);
编辑:我应该补充一点,我同意弗雷德里克.您使用List的方式与首先使用它的整个推理背道而驰.
EDIT2:
编辑2:我目前正在编写的是一个基类,它提供默认功能作为更大框架的一部分.在我提供的默认功能中,List的大小在高级中是已知的,因此我可以使用数组.但是,我想为任何基类提供动态扩展它的机会,因此我选择了一个列表.
为什么有人需要知道具有所有空值的List的大小?如果列表中没有实际值,我希望长度为0.无论如何,这是cludgy的事实表明它违背了类的预期用途.
如果要使用固定值初始化它,为什么使用List?我可以理解 - 为了性能 - 你想给它一个初始容量,但它不是一个列表比常规数组的优点之一,它可以在需要时增长?
当你这样做:
List= new List (100);
您创建一个容量为100整数的列表.这意味着在添加第101个项目之前,您的列表不需要"增长".列表的基础数组将初始化为100.
首先创建一个数组,其中包含所需的项目数,然后将其转换为列表。
int[] fakeArray = new int[10]; Listlist = fakeArray.ToList();
初始化列表的内容不是真正的列表.列表旨在容纳对象.如果要将特定数字映射到特定对象,请考虑使用键值对结构,如散列表或字典而不是列表.