C# 如果从列表中删除某个特定项<;T>;它是否也删除了';空插槽';?

C# 如果从列表中删除某个特定项<;T>;它是否也删除了';空插槽';?,c#,C#,请随时更正我的术语,如果需要,请理解列表 如果我有一个五个项目的列表,其中每个项目都有一个唯一的ID [item 1] [item 2] [item 3] [item 4] [item 5] 我删除了ID为72的项目(例如),它恰好是列表中的第三个 会不会就这样结束 [item 1] [item 2] [null] [item 4] [item 5] 还是像这样 [item 1] [item 2] [item 3] [item 4] 过去是第4项,现在是第3项,等等 如果可以,请解释:)第

请随时更正我的术语,如果需要,请理解列表

如果我有一个五个项目的列表,其中每个项目都有一个唯一的ID

[item 1]
[item 2]
[item 3]
[item 4]
[item 5]
我删除了ID为72的项目(例如),它恰好是列表中的第三个

会不会就这样结束

[item 1]
[item 2]
[null]
[item 4]
[item 5]
还是像这样

[item 1]
[item 2]
[item 3]
[item 4]
过去是第4项,现在是第3项,等等


如果可以,请解释:)

第二个选项。它的行为类似于数组,而不是数组

可以删除特定索引处的元素。在该点和更高的指数处,先前元素的指数减少1


我的陈述已经通过技术观察得到了纠正,但出于可枚举的目的,一个列表对象,当您删除一个项时,它就消失了,就像您的第二个示例一样


实际上,随着
System.Collections.Generic.List的实现,用于存储项的底层数组将以如下方式结束:

[item 1]
[item 2]
[item 4]
[item 5]
[null]
[item 1]
[item 2]
[item 4]
[item 5]
[default(item)]
[item 1]
[item 2]
[item 3]
[item 4]
[item 5]
[default(item)]
[default(item)]
[default(item)]
也就是说,在不改变数组大小的情况下,第3项已被删除,第4项和第5项已被移动

当然,如果枚举集合,后面的null将被忽略,因为集合的大小用于确定停止的位置。(编辑:并尝试访问集合逻辑结尾以外的标记将失败。)

在您的示例中

[item 1]
[item 2]
[item 3]
[item 4]
[item 5]
如果删除[item 3],则List类只会将该项后面的数组部分复制到items索引中,列表的内部数组如下所示:

[item 1]
[item 2]
[item 4]
[item 5]
[null]
[item 1]
[item 2]
[item 4]
[item 5]
[default(item)]
[item 1]
[item 2]
[item 3]
[item 4]
[item 5]
[default(item)]
[default(item)]
[default(item)]
但是,您不能访问现在的最后一个项目,因为列表保留一个大小变量来跟踪可访问的项目数。实际上,这个列表看起来像是外部的第二个示例,但是内部数组实际上可以更大

编辑: 还请注意,在现实中,数组要比这个大得多,因为在插入项目时列表会调整其大小(当没有足够的空间容纳新项目时,它会将数组大小增加一倍)。例如,如果向列表中添加5个项目,则列表将如下所示:

[item 1]
[item 2]
[item 4]
[item 5]
[null]
[item 1]
[item 2]
[item 4]
[item 5]
[default(item)]
[item 1]
[item 2]
[item 3]
[item 4]
[item 5]
[default(item)]
[default(item)]
[default(item)]

这不是100%正确。如果T是值类型,则列表数组中的最后一项不是null,而是该值类型的默认值。注意,由于这种行为,在foreach迭代中不能修改列表的内容,因为foreach的条件不能更改。使用列表时,不会删除“空槽”。元素通过数组进行移位。复制,现在无效的最后一个“空槽”用默认值(T)填充。@dkson和新的“空槽”将位于列表的最末尾?@Shogun:是的,但您无法从外部“查看”或访问它,因为列表类有一个名为_size的私有成员。此成员保留列表中的项目数,但与列表中用于实际存储项目的数组大小无关。请看下面我的答案。@dkson那么,这是否意味着如果我以这种方式删除它,实际上并没有释放资源?就像我正在建立一堆“空槽”?很好,所以不管我应该关心什么,我很好奇这是否意味着我的列表可能永远不会真正缩小,只会增长,就像我删除了一些东西一样,它在深处保持相同的大小,对吗?除非调用
trimOverse()
或设置
容量
属性。
列表
实现在任何时候都会修剪阵列,除非您明确要求修剪。