问题描述
.NET 提供了一个通用列表容器,其性能几乎相同(请参阅数组与列表的性能问题).但是,它们在初始化方面完全不同.
.NET offers a generic list container whose performance is almost identical (see Performance of Arrays vs. Lists question). However they are quite different in initialization.
数组很容易用默认值初始化,并且根据定义它们已经具有一定的大小:
Arrays are very easy to initialize with a default value, and by definition they already have certain size:
string[] Ar = new string[10];
这允许人们安全地分配随机项目,例如:
Which allows one to safely assign random items, say:
Ar[5]="hello";
使用列表的事情更加棘手.我可以看到两种进行相同初始化的方法,这两种方法都不是你所说的优雅:
with list things are more tricky. I can see two ways of doing the same initialization, neither of which is what you would call elegant:
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"
The answers so far refer to capacity, which is something else than pre-populating a list. For example, on a list just created with a capacity of 10, one cannot do L[2]="somevalue"
编辑 2:人们想知道我为什么要以这种方式使用列表,因为这不是它们的预期使用方式.我可以看到两个原因:
EDIT 2: People wonder why I want to use lists this way, as it is not the way they are intended to be used. I can see two reasons:
人们可以非常有说服力地争辩说,列表是下一代"数组,增加了灵活性,几乎没有任何损失.因此,应该默认使用它们.我指出它们可能不那么容易初始化.
One could quite convincingly argue that lists are the "next generation" arrays, adding flexibility with almost no penalty. Therefore one should use them by default. I'm pointing out they might not be as easy to initialize.
我目前正在编写的是一个基类,它提供默认功能作为更大框架的一部分.在我提供的默认功能中,列表的大小是预先知道的,因此我可以使用数组.但是,我想为任何基类提供动态扩展它的机会,因此我选择了一个列表.
What I'm currently writing is a base class offering default functionality as part of a bigger framework. In the default functionality I offer, the size of the List is known in advanced and therefore I could have used an array. However, I want to offer any base class the chance to dynamically extend it and therefore I opt for a list.
推荐答案
我不能说我经常需要这个 - 你能详细说明你为什么需要这个吗?我可能会把它作为一个静态方法放在一个辅助类中:
I can't say I need this very often - could you give more details as to why you want this? I'd probably put it as a static method in a helper class:
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()
但由于缓冲区大小调整,这样做效率低.
You could use Enumerable.Repeat(default(T), count).ToList()
but that would be inefficient due to buffer resizing.
请注意,如果 T
是引用类型,它将存储 count
个为 value
参数传递的引用的副本 - 因此它们将都指同一个对象.这可能是也可能不是您想要的,具体取决于您的用例.
Note that if T
is a reference type, it will store count
copies of the reference passed for the value
parameter - so they will all refer to the same object. That may or may not be what you want, depending on your use case.
如评论中所述,如果您愿意,可以使 Repeated
使用循环来填充列表.那也会稍微快一点.我个人发现使用 Repeat
的代码更具描述性,并怀疑在现实世界中性能差异无关紧要,但您的里程可能会有所不同.
As noted in comments, you could make Repeated
use a loop to populate the list if you wanted to. That would be slightly faster too. Personally I find the code using Repeat
more descriptive, and suspect that in the real world the performance difference would be irrelevant, but your mileage may vary.
这篇关于如何初始化列表<T>到给定的大小(而不是容量)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!