List.RemoveAt(index)是如何工作的?

本文关键字:工作 何工作 RemoveAt index List | 更新日期: 2023-09-27 17:51:03

假设我有一个列表,消息,有三个项目。我不想循环遍历它们,每次删除一个项。

for (int i = 0; i < messages.Count; i++)
{ 
    messages.RemoveAt(i);
}

(我已经删除了很多不相关的代码)

第一次迭代之后剩下的消息会发生什么?它们是否被移动到另一个索引中,或者我可以这样做以删除所有三条消息?

谢谢

List.RemoveAt(index)是如何工作的?

您删除的索引后面的所有元素的索引将被递减。如果你想在循环中避免这种情况,让它反向运行(从最高索引到最低索引删除)。

for (int i = messages.Count - 1; i >= 0; i--)
{ 
    messages.RemoveAt(i);
}

或者直接用

messages.Clear()

一次删除所有元素,而不考虑任何索引。

如果你只想清除List,使用Clear也更有效,因为它是一个O(n)操作。RemoveAt也是O(n),但在另一个O(n)循环中使它成为O(n^2) -这与你的例子中提到的3个元素无关,但当谈论更大的列表时,它肯定会有所不同。

在您的代码中,调用messages.Clear();更简单。没有必要单独删除每个元素。

您的代码将跳过所有其他元素,因为它删除它们,直到for循环的条件不再满足。它将删除索引0和2处的元素,因为您说您的集合有三个元素。

让我们通过你的算法:

最初,列表有三个项目,按它们的索引列出:0:"Hello",1:"World"和2:"Foo"。

循环删除索引0处的元素。列表现在看起来像这样:

0: "World", 1: "Foo"

然而,你的循环再次执行,因为i现在等于1和1 < 2。然后删除索引1处的元素:

0:"世界"

i被增加到2,并且不再满足条件(i不小于1)。你的列表现在由原来的第二个元素组成。

需要反向迭代

for (int i = messages.Count - 1; i >=0; i--)
{
    messages.RemoveAt(i);
}

因为在当前循环中,如果列表包含3个项目,则只剩下一次。

如果你想从列表中删除所有项目,那么有一个方法List<T>.RemoveAll Method

它们被移动了,参见MSDN on List<T>.RemoveAt method:

当你调用RemoveAt来删除一个项时,中剩余的项列表被重新编号以替换被删除的项。例如,如果你删除索引3处的项,将索引4处的项移到3处位置。

删除所有元素,Clear方法更合适。

执行反向循环…

  for(int i = messages.Count - 1; i >= 0 ; i--) {
    messages.RemoveAt(i);
}

你可以把它改成总是删除第一个

List<string> messages = new List<string>();
messages.Add("a"); 
messages.Add("b");
messages.Add("c");
for (int i = 0; i < messages.Count; i++)
{
     messages.RemoveAt(0);
}

或在一条语句中清除整个列表

messages.Clear()

。. NET参考源代码中有以下RemoveAt方法的定义:

public void RemoveAt(int index) 
{
    if ((uint)index >= (uint)_size)             
        ThrowHelper.ThrowArgumentOutOfRangeException();            
    Contract.EndContractBlock();
    _size--;
    if (index < _size) 
        Array.Copy(_items, index + 1, _items, index, _size - index);
    _items[_size] = default(T);
    _version++;
}

正如你所看到的-如果你删除的项目不是最后一个复制数组项目发生(从索引+ 1到最后的所有项目都被移动)。因此,在您的情况下,最好从末尾删除项,以避免每次迭代时数组复制:

for (int i = messages.Count - 1; i >= 0; i--)
{
    messages.RemoveAt(i);
}

或者简单地调用messages.Clear(),如果你想删除它们而不需要额外的逻辑-在这种情况下,内部数组刚刚被清除,大小设置为零。

与其他帖子一样,您需要向后迭代

你有很多方法来删除项目

messages.Clear(); 

while(messages.Count != 0){
    message.RemoveAt(0);
}