Problem overview
The program should print one opening line, then a greeting and a question for each student, and finally a closing line:
What a nice day!
Hey, Andy
How are you?
Hey, Mike
How are you?
Hey, Mary
How are you?
Let's start the class!
The buggy code doesn't even compile, so there is no output to compare. The compiler complains about the name student. Fixing that error, and then the order, takes two observations.
Approach
Why the compiler complains
The loop variable student exists only inside the braces of the foreach. The last line of the buggy code uses it after the closing brace:
foreach (string student in students) {
Console.WriteLine("What a nice day!");
}
Console.WriteLine("How are you?");
Console.WriteLine("Hey, " + student); // error: student is out of scope here
The compiler reports that the name student does not exist in the current context. Once the loop is over, the variable is gone. Any statement that needs the student must be inside the loop.
Sorting the lines into three groups
Sort every message by how often it should appear:
- Once, at the start:
What a nice day!, so it goes before the loop. - Once per student:
Hey,plus the name, followed byHow are you?, so both go in the loop body, in that order. - Once, at the end:
Let's start the class!, so it goes after the loop.
Step by step
- Print the opening line first. Put
What a nice day!above theforeach. - Fill the loop body. Print the greeting with the student's name, then
How are you?. Both calls now sit inside the braces, so the compiler can seestudent. - Close the loop, then print the final line.
Let's start the class!comes after the closing brace, so it runs once.
The solution in C#
string[] students = {"Andy", "Mike", "Mary"};
Console.WriteLine("What a nice day!");
foreach (string student in students) {
Console.WriteLine("Hey, " + student);
Console.WriteLine("How are you?");
}
Console.WriteLine("Let's start the class!");
Running it prints the eight expected lines. Here is the flow: the opening line, then three passes through the loop body (one per student), and finally the closing line once the loop has ended.
Tracing the fixed program
Following the flow of the fixed program makes the structure concrete:
- The array is created with three names.
What a nice day!is printed. This statement is before the loop, so it runs one time.- The loop starts. With
studentset to"Andy", it printsHey, Andyand thenHow are you?. Thenstudentbecomes"Mike"and the same two lines run, and then"Mary". - The array has no more elements, so the loop ends and the variable
studentgoes out of scope. Let's start the class!is printed, once.
Edge cases and common mistakes
- Using a loop variable after the loop. This is the error in the lesson's code. A variable declared in the
foreachheader lives only in the loop. If you need a value after the loop, declare a separate variable before it. - Swapping the greeting and the question. Within the body the order matters. Putting
How are you?first would print the question before each name. - Getting the right lines in the wrong place. A program can compile and still print the lines in a different order. Compare the output line by line with the expected text, not only the set of messages.
- Counting output lines. With three students, the loop contributes six lines, and the two outside statements add two more, so eight in total. If you see a different count, one statement is probably inside or outside the loop when it shouldn't be.
- Fixing only the compile error. Moving the last line into the loop would make the program compile, but the output would still be in the wrong order. After the program compiles, compare the output with the expected text.