C# 是否提前在 List<Object> 上保留三个空实例?

Does C# reserve three null instances ahead of time on a List<Object>?

我有以下内容:

 public static class LocalFileModelList
    {
        public static List<LocalFileModel> ModelList = new List<LocalFileModel>();
    }

    public class LocalFileModel
    {
        public string Name { get; set; }
        public string Extension { get; set; }
    }

然后是一个从目录中读取所有文件的方法。

public static List<LocalFileModel> GetAllFiles(string path)
{
    var files = Directory.GetFiles(path, "*.*");

    foreach(var file in files)
    {
        var Extension    = Path.GetExtension(file);
        var Filename     = Path.GetFileNameWithoutExtension(file);

        var model = new LocalFileModel
        {
            Name         = Filename,
            Extension    = Extension,
        };

        LocalFileModelList.ModelList.Add(model);     
    }

    return LocalFileModelList.ModelList;
}

我注意到,当我逐步执行我的代码时,当我创建 LocalFileModel 的新实例时,用数据填充它然后将它添加到列表中。该列表自动创建了三个类型为 null 的实例。一旦这三个填充了各自的对象,它就会再次创建三个空实例...

我现在才发现,这正常吗?

是的。 .NET 和大多数其他库分配具有额外 space(容量)的列表或向量,因此它不必经常调整大小和复制数据。 Size 决定什么是可访问的。

默认容量在这里定义为 4(但文档不一定是):

http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,aa9d469618cd43b0,references

List<T> 有一个内部数组,其容量总是等于或大于列表中的项目数。

list.Capacity >= list.Count

你实际上可以告诉列表它的内部数组应该用什么容量创建。

new List<int>(capacity: 5);

当插入一个项目并且数组达到其容量时,列表会创建一个新数组,其大小是以前的两倍以容纳新元素。因此,在您的情况下,如果您要插入第 5 个项目,列表将分配一个具有 8 个插槽的新内部数组(其中 5 个将被填充)。

有关更多详细信息,请查看实施 here

List<T> 持有的内部数组的 initial capacity 是 4(目前,这是一个实现细节,可能会改变),当然你添加了一个初始值。一旦您开始填充列表,它每次都会自行调整 2 的倍数。这就是为什么当你提前知道最小项目的数量时,你可以使用重载 int capacity (或者如果它确实是固定大小,则使用数组)。

List<T> 由数组支持。 List<T> 的 default/Initial 容量定义为 4reference source 一样,但只有在将项目添加到列表中后才会生效。

 public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
    {
        private const int _defaultCapacity = 4;

因此,当您在 List 中添加第一项时,使用 EnsureCapacity 方法中的以下 check 将大小设置为 4

int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;

稍后,随着每个新项目被添加到列表中,容量增加到 Number of Elements * 2

这就是为什么当您添加第一项时,您会看到三个 null 个空格,列表中保留了另外三个空格。