是什么导致了这里的 IndexOutOfRangeException?

What causes IndexOutOfRangeException here?

我参加了一次编程考试,最后,我总是对下面的代码(对于 if 语句,确切地说)有一个 IndexOutOfRangeException

任务是从列表中删除 21..32 范围内的数字,然后打印出新列表。 numsList<int> 正好有 6 个用户给出的数字。

我已经编程 4 年了,我找不到一个问题:D

这是代码。

// nums is a List<int> with exactly 6 elements in it.
List<int> changedNums = new List<int>(nums);
            
for (int k = 0; k < 6; k++)
    if (changedNums[k] >= 21 && changedNums[k] <= 32)
        changedNums.RemoveAt(k);

我没有在这里加上括号,因为它是单行的。

这里的问题是您在迭代时修改了列表的长度。从 changedNums 列表中删除至少一项后,它的长度小于最初的 6(所以你得到 IndexOutOfRangeException)。此外,一旦您删除了第 k 个项目,您应该减少 k。我修改了您的示例代码以按如下方式工作:

static void Main()
{
    List<int> nums = new List<int>() { 1, 22, 30, 4, 5, 6 };
    List<int> changedNums = new List<int>(nums);
            
    var currentLength = changedNums.Count;
    for (int k = 0; k < currentLength; k++)
    {
        if (changedNums[k] >= 21 && changedNums[k] <= 32)
        {
            changedNums.RemoveAt(k);
            --k;
            --currentLength;
        }
    }
    
    Console.WriteLine(string.Join(" ", changedNums));
}

这将打印:1 4 5 6

编辑:

正如@derpirscher 和@Jon Skeet 在评论中指出的那样,通过从头到尾迭代数组可以轻松避免索引操作:

List<int> nums = new List<int>() { 1, 22, 30, 4, 5, 6 };
List<int> changedNums = new List<int>(nums);
        
for (int k = changedNums.Count - 1; k >= 0 ; k--)
    if (changedNums[k] >= 21 && changedNums[k] <= 32)
        changedNums.RemoveAt(k);

Console.WriteLine(string.Join(" ", changedNums));

使用 LINQ 可以更简单地解决您的问题:

var changedNums = nums.Where(num => num < 21 || num > 32).ToList();

所有的解都会产生相同的结果1 4 5 6