Problem overview
PrintSum is supposed to add up every number in the array nums and print the total once. MainFunction calls it with 1, 2, 3, so the expected output is a single line:
6
The code in the editor prints three lines instead:
1
2
3
There are two separate mistakes, and both have to be fixed. Fixing only one gives a different wrong output.
Why the code goes wrong
Here is the buggy method:
public void PrintSum(int[] nums) {
foreach (int num in nums) {
int sum = 0;
sum += num;
Console.WriteLine(sum);
}
}
The easiest way to find the problems is to trace the loop by hand and write down what sum is on each pass.
| Pass | num | sum after int sum = 0 | sum after sum += num | Printed |
|---|---|---|---|---|
| 1 | 1 | 0 | 1 | 1 |
| 2 | 2 | 0 | 2 | 2 |
| 3 | 3 | 0 | 3 | 3 |
Mistake 1: the variable is declared inside the loop
A variable declared inside a loop body is created fresh on every pass and disappears at the closing brace. So int sum = 0 resets the total to zero each time, and the earlier numbers are forgotten before the next one arrives. The running total has to live outside the loop, where it survives from one pass to the next.
Mistake 2: the print is inside the loop
Even with the declaration moved out, Console.WriteLine(sum) inside the loop prints after every addition. The output would be the running totals 1, 3 and 6 on separate lines. The total is only complete after the last number has been added, so the print belongs after the loop.
The intermediate state is worth seeing, because it is a common half-fix:
public void PrintSum(int[] nums) {
int sum = 0;
foreach (int num in nums) {
sum += num;
Console.WriteLine(sum); // still wrong: prints 1, 3, 6
}
}
The fix in C#
Move the declaration above the loop and the print below it. Leave MainFunction as it is:
public void PrintSum(int[] nums) {
int sum = 0;
foreach (int num in nums) {
sum += num;
}
Console.WriteLine(sum);
}
public void MainFunction() {
PrintSum(new int[]{1, 2, 3});
}
Now the three stages are clear: set up the accumulator, update it once per element, and report the result when the loop is over.
- Initialize before the loop.
int sum = 0runs exactly once. Zero is the right starting value because adding zero to a number changes nothing. foreachvisits every element. It gives you each value ofnumsin order, in the variablenum, with no index to manage.- Print after the closing brace. The statement runs once, with the finished total, so the output is the single line
6.
The scope rule behind it
C# has a general rule: a variable lives from its declaration to the end of the block, the pair of braces, that contains it. Declared inside the loop's braces, sum belongs to one pass only. Declared in the method's braces, before the loop, it is visible to the whole loop and to the code after it. A variable you want to keep across iterations, such as a total, a count or a maximum, is declared before the loop.
C# also protects you in one related case. Using sum after the loop would not compile if it had been declared inside, because the name no longer exists there. The compiler reports an error instead of letting you read a stale value.
Edge cases and common mistakes
- An empty array. The loop never runs,
sumstays 0, and the method prints0. That is the correct sum of no numbers. - Negative numbers. They need no special handling:
sum += numsubtracts whennumis negative. - Printing at the wrong place. Moving the declaration out of the loop but leaving the print inside gives running totals. When the output is right but repeated, look at where the print sits.
- Moving the declaration but forgetting to keep it before the loop. Putting
int sum = 0after the loop's opening brace, or after the loop, either resets the total or fails to compile. - Overflow. An
intsum wraps around silently if the true total passes 2,147,483,647. The small arrays in this lesson never get close, but alongtotal is the safer choice for large data.
Testing
new int[]{1, 2, 3}prints6.new int[]{5}prints5.new int[]{-2, 2}prints0.new int[]{}prints0.