Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

What causes IndexOutOfRangeException here?

I had a programming exam where at the end, I always had an IndexOutOfRangeException for the code below (for the if statement, exactly).

The task was to remove numbers in 21..32 range from the list then print out the new list. nums is a List<int> with exactly 6 numbers given by the user.

I’ve been programming for 4 years now and I can’t find a single problem 😀

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Here’s the code.

// 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);

I didn’t put brackets here because it’s a one-liner.

>Solution :

The issue here is that you modifying the length of the list while iterating. After you deleted at least one item from changedNums list, its length is less than the initial 6 (so you get IndexOutOfRangeException). Also, once you deleted k-th item, you should decrement k. I modified your sample code to work as follows:

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));
}

This will print: 1 4 5 6

Edit:

As pointed by @derpirscher and @Jon Skeet in comments, index manipulations can be easily avoided by iterating the array from end to start:

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));

An even easier solution to your problem can be achieved using LINQ:

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

All the solutions will produce the same result 1 4 5 6

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading