是什么导致了这里的 IndexOutOfRangeException?
What causes IndexOutOfRangeException here?
我参加了一次编程考试,最后,我总是对下面的代码(对于 if 语句,确切地说)有一个 IndexOutOfRangeException
。
任务是从列表中删除 21..32 范围内的数字,然后打印出新列表。 nums
是 List<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
我参加了一次编程考试,最后,我总是对下面的代码(对于 if 语句,确切地说)有一个 IndexOutOfRangeException
。
任务是从列表中删除 21..32 范围内的数字,然后打印出新列表。 nums
是 List<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