如何初始化一个列表到一个给定的大小(而不是容量)?

问题描述:

.NET提供了一个通用列表容器,其性能几乎相同(请参阅数组与列表性能问题)。然而,它们在初始化方面有很大不同如何初始化一个列表<T>到一个给定的大小(而不是容量)?

数组是很容易用默认值进行初始化,并定义他们已经有一定的规模:

string[] Ar = new string[10]; 

,使人们能够安全地分配随机物品,说:

Ar[5]="hello"; 

与列出事情更棘手。我可以看到在做相同的初始化两种方式,这两者都不是你称之为优雅:

List<string> L = new List<string>(10); 
for (int i=0;i<10;i++) L.Add(null); 

string[] Ar = new string[10]; 
List<string> L = new List<string>(Ar); 

这将是一个更清洁的方式?

编辑:到目前为止的答案是指能力,这是比预填充列表别的东西。例如,在刚创建的容量为10的列表上,人们不能这样做L[2]="somevalue"

编辑2:人们想知道为什么我想以这种方式使用列表,因为它不是它们打算使用的方式。我可以看到两个方面的原因:

  1. 人们可以令人信服地认为,名单是“下一代”阵列,增加了灵活性,几乎没有损失。因此,应该默认使用它们。我指出他们可能不容易初始化。

  2. 我现在写的是一个基类,它提供了作为更大框架一部分的默认功能。在我提供的默认功能中,List的大小在高级中是已知的,因此我可以使用一个数组。但是,我想为任何基类提供动态扩展的机会,因此我选择了一个列表。

+1

“编辑:答案至今指容量,这是除了预填充之外的其他内容名单。举例来说,只是一个容量10创建的列表上,一个人不能做L [2] =“someValue中”” 鉴于此修改,也许你应该改写的问题标题...... – aranasaurus 2009-01-21 21:03:36

+0

可是,有什么用预-populating空值的列表,导致这就是该topicstarter试图做 – 2009-01-21 21:04:48

+0

弗雷德里克:?什么时候会变成这样......需要不断 – 2009-01-21 21:05:29

我不能说我经常需要这个 - 你能给出更多的细节,为什么你想要这个?我可能会把它作为一个静态方法的辅助类:

public static class Lists 
{ 
    public static List<T> RepeatedDefault<T>(int count) 
    { 
     return Repeated(default(T), count); 
    } 

    public static List<T> Repeated<T>(T value, int count) 
    { 
     List<T> ret = new List<T>(count); 
     ret.AddRange(Enumerable.Repeat(value, count)); 
     return ret; 
    } 
} 

可以使用Enumerable.Repeat(default(T), count).ToList()但是这将是低效的,由于缓冲区大小调整。

编辑:正如在评论中指出的,你可以让Repeated使用循环来填充列表,如果你想。这也会稍微快一点。就我个人而言,我发现使用Repeat的代码更具描述性,并且怀疑在现实世界中,性能差异将无关紧要,但是您的里程可能会有所不同。

使用这需要一个int( “能力”)作为参数的构造:

List<string> = new List<string>(10); 

编辑:我要补充一点,我弗雷德里克同意。您使用List的方式与首先使用它的背后的全部理由背道而驰。

EDIT2:

编辑2:什么我目前正在写一个基类产品默认的功能更大的框架的一部分。在我提供的默认功能中,List的大小在高级中是已知的,因此我可以使用一个数组。但是,我想为任何基类提供动态扩展的机会,因此我选择了一个列表。

为什么任何人需要知道所有空值的列表大小?如果列表中没有真正的值,我会预期这个长度为0.总而言之,这是一个错误,这表明它违背了该类的预期用途。

为什么你要使用列表,如果你想用固定值初始化它? 我可以理解 - 为了性能 - 你想给它一个初始容量,但是不是常规数组上的列表的优点之一,它可以在需要时增长?

当你这样做:

List<int> = new List<int>(100); 

创建,其容量为100个整数的列表。这意味着你的列表不需要“增长”,直到你添加第101项。 列表的底层数组将被初始化为100的长度。

初始化列表中的内容实际上不是列表的内容。列表旨在保存对象。如果要将特定数字映射到特定对象,请考虑使用键值对结构,如散列表或字典而不是列表。

这真的取决于你为什么要初始化它。我不确定用一定数量的空或空元素初始化它是有用的。列表的优点是,它们可以根据需要增长。

列表构造函数需要一个容量参数,它可以用来初始填充它。

List<string> = new List<string>(10); 

string [] temp = new string[] {"1","2","3"}; 
List<string> temp2 = temp.ToList(); 

如果你想初始化一些固定值的N个元素的列表:

public List<T> InitList<T>(int count, T initValue) 
{ 
    return Enumerable.Repeat(initValue, count).ToList(); 
} 

你似乎在强调与您的数据的位置关联的需要,所以止跌”联合数组更合适吗?

Dictionary<int, string> foo = new Dictionary<int, string>(); 
foo[2] = "string"; 

List<string> L = new List<string> (new string[10]); 

你可以使用LINQ到一个默认值初始化巧妙您的列表。 (到David B's answer类似。)

var defaultStrings = (new int[10]).Select(x => "my value").ToList(); 

转到一个步骤更远并初始化每个字符串与不同的值 “串1”, “字符串2”, “字符串3”,等:

int x = 1; 
var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList(); 

创建数组,其中包含您想要的项目数量,然后将数组转换为List。

int[] fakeArray = new int[10]; 

List<int> list = fakeArray.ToList(); 

约IList中通知: MSDN IList Remarks: “的IList实现分为三类:。只读,固定大小的,并大小可变的(...)对于该接口的通用版本,见 System.Collections.Generic.IList<T>。“

IList<T>不继承IList(但不List<T>同时实现IList<T>IList),但始终是variable-size。 自.NET 4.5以来,我们也有IReadOnlyList<T>但AFAIK,没有固定大小的通用列表,这将是你在找什么。

这是我用我的单元测试的样本。我创建了一个类对象列表。然后,我使用forloop添加了我希望从服务中获得的“X”个对象。 这样你可以为任何给定的大小添加/初始化列表。

public void TestMethod1() 
    { 
     var expected = new List<DotaViewer.Interface.DotaHero>(); 
     for (int i = 0; i < 22; i++)//You add empty initialization here 
     { 
      var temp = new DotaViewer.Interface.DotaHero(); 
      expected.Add(temp); 
     } 
     var nw = new DotaHeroCsvService(); 
     var items = nw.GetHero(); 

     CollectionAssert.AreEqual(expected,items); 


    } 

希望我对你们有所帮助。

你提出

有点晚了,但第一个解决方案似乎更干净对我说:你不分配内存的两倍。甚至列表constrcutor需要通过数组循环以复制数组;它甚至不知道预先在里面只有空元素。

1. - 分配Ñ - 循环N 成本:1 *分配(N)+ N * loop_iteration

2. - 分配Ñ - 分配N +环() 成本:2 *分配(N)+ N * loop_iteration

但是名单的分配,因为名单是一个循环可能会更快内置类,但C#是JIT编译SOOO ...