0

So I tried googling but I can't find any information that answers my question.

Basically I have an array that consists out {1,2,3,4,5,6,7,8,9,10}. I have a for loop and a foreach loop that as far as i know do the same thing (print only the numbers divisible by 2). The for loop works fine - it prints 2,4,6,8 and 10. The foreach loop also seems to print the correct integers, but for some reason it throws a IndexOutOfRangeExeption. Why does the for loop work completly fine with no errors, but the foreach loop prints the correct integers but still throws an error?

Here is the code:

int[] tenNums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Console.WriteLine(tenNums.Length);

for (int i = 0; i < tenNums.Length; i++)
{
    if (tenNums[i] % 2 == 0)
    {
        Console.WriteLine(tenNums[i]);
    }
}

foreach (int i in tenNums)
{
    if (tenNums[i] % 2 == 0) // <== Error happens on this line
    {
        Console.WriteLine(tenNums[i]);
    }
}
Console.ReadKey();
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
P. Protas
  • 416
  • 4
  • 15

6 Answers6

8
foreach (int i in tenNums)
{
    if (tenNums[i] % 2 == 0) // <== Error happens on this line
    {
        Console.WriteLine(i);
    }
}

In this foreach, i will successively take the value of every value inside of tenNums. So i is not an index you are incrementing anymore there. You are trying to access memory which is not allocated for the array when using the number 10 as an index. Change it so that you check i instead:

foreach (int i in tenNums)
{
    if (i % 2 == 0)
    {
        Console.WriteLine(i);
    }
}
Izuka
  • 2,572
  • 5
  • 29
  • 34
  • 2
    Thank you, your solution worked. So as i understood it, my code basically said tenNums[tenNums[9]] which equals tenNums[10] which didn't exist. – P. Protas Sep 08 '17 at 12:31
  • @P.Protas Exactly! Leading to the IndexOutOfRangeException. – Izuka Sep 08 '17 at 12:35
4

The for loop starts at 0 and goes up to 9. The foreach starts at the first value of 1 and goes up to the last value of 10. When you access the array with the indexer it is 0 indexed, so you have an off by one error.

What you actually want is this:

foreach (int i in tenNums)
{
    if (i % 2 == 0) // <= No need to use the indexer since we already have the value
    {
        Console.WriteLine(i);
    }
}
Owen Pauling
  • 11,349
  • 20
  • 53
  • 64
2

When using a foreach loop you should use i rather than tenNums[i].

So:

foreach (int i in tenNums)
{
    if (i % 2 == 0)
    {
        Console.WriteLine(i);
    }
}

That is basically the point of a foreach in this context - to avoid having to use tenNums[i].

Even the error you are experiencing shows the benefit of foreach. When using tenNums[something] you always have to be concerned about whether something is actually valid or not (e.g. you may have an off-by-one error). With foreach there is no such concern - i will work.

mjwills
  • 23,389
  • 6
  • 40
  • 63
1

Your first for loop will use 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9.

Your second foreach loop will use 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10 because those are the values in the array.

And what happens on tenNums[10]? An error!

corsiKa
  • 81,495
  • 25
  • 153
  • 204
1

Pretty simple.
instead of this:

if (tenNums[i] % 2 == 0)
{
    Console.WriteLine(tenNums[i]);
}

Use this:

if (i % 2 == 0)
{
    Console.WriteLine(i);
}
OMKAR AGRAWAL
  • 128
  • 1
  • 9
1

Because you are trying to access tenNums[10] (10th item of tenNums) in foreach loop.

ITSGuru
  • 194
  • 8