一尘不染

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

c#

.NET提供了一个通用的列表容器,其性能几乎相同(请参见阵列性能与列表性能问题)。但是,它们在初始化方面大不相同。

数组很容易使用默认值初始化,并且根据定义,它们已经具有一定的大小:

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. 我当前正在编写的是一个基类,该基类提供默认功能,作为更大框架的一部分。在我提供的默认功能中,列表的大小是高级已知的,因此我可以使用数组。但是,我想为任何基类提供动态扩展它的机会,因此我选择了一个列表。


阅读 318

收藏
2020-05-19

共1个答案

一尘不染

我不能说我经常需要-您能否提供更多为什么要这样做的详细信息?我可能会将其作为静态方法放在帮助器类中:

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()但是由于缓冲区大小调整,效率会很低。

请注意,如果T是引用类型,它将存储countvalue参数传递的引用的副本-
因此它们都将引用同一对象。这可能取决于您的用例,也可能不是您想要的。

编辑:如注释中所述,如果需要,您可以Repeated使用循环来填充列表。那也会稍微快一点。我个人认为代码使用的是Repeat更具描述性的,并且怀疑在现实世界中,性能差异是无关紧要的,但是您的工作量可能会有所不同。

2020-05-19