Loops in C# allow you to execute a block of code repeatedly without writing the same statements multiple times. They are fundamental programming constructs used to process collections, repeat calculations, validate user input, generate reports, and automate tasks.
Imagine building a quiz application that needs to display ten questions, evaluate every student's score, or print all available courses on a page. Writing a separate statement for every item would make your code unnecessarily long and difficult to maintain. A loop allows you to handle these operations with a small, reusable block of logic.
C# provides four commonly used loops: for, while, do-while, and foreach. Each has a different purpose. The for loop is useful when you control an index or iteration count, while repeats while a condition remains true, do-while checks its condition after executing the body, and foreach processes elements in a collection.
1. The for Loop
The for loop is commonly used when the number of iterations is known or when you need explicit control over an index. Its header contains three parts: initialization, a continuation condition, and an iteration expression. These parts determine where the loop begins, when it stops, and how its control variable changes.
The general syntax is:
for (initialization; condition; iteration)
{
// Statements to repeat
}
Initialization normally runs once before the first iteration. Before each execution of the loop body, C# evaluates the condition. If it is true, the body executes and then the iteration expression runs. If the condition is false, the loop finishes.
for (int i = 1; i <= 5; i++)
{
Console.WriteLine($"Question {i}");
}
This code prints questions numbered from 1 to 5. The variable i starts at 1, the condition allows the loop to continue while i is less than or equal to 5, and i++ increases its value after every iteration.
The increment operator ++ increases a numeric variable by one. You can also use i-- to decrease it or an expression such as i += 2 to increase it by two. Ensure that the iteration expression eventually makes the condition false; otherwise, the loop may continue indefinitely.
2. The while Loop
The while loop repeats a block as long as its condition evaluates to true. Unlike a typical counting for loop, it is particularly useful when the number of repetitions depends on changing application state, user input, or a condition that cannot be determined in advance.
int score = 0;
while (score < 3)
{
Console.WriteLine("Keep practicing!");
score++;
}
The message appears three times. The condition is evaluated before each iteration, and the counter increases inside the loop body. When score reaches 3, the condition becomes false and execution continues after the loop.
Because the condition is checked before the body executes, a while loop may run zero times. For example, if score already equals 3 before the loop begins, the body will not execute at all.
While loops are useful for retrying an operation, processing input while it remains available, and repeating an action until a particular state is reached. If a loop depends on user input or an external operation, make sure it also handles cancellation, errors, and termination conditions correctly.
3. The do-while Loop
A do-while loop is similar to a while loop, but it checks the condition after executing the body. This guarantees that the loop body runs at least once, even when the condition is initially false.
int attempts = 1;
do
{
Console.WriteLine($"Attempt {attempts}");
attempts++;
}
while (attempts <= 3);
This example prints three attempts. The variable increases after each message, and the condition is checked at the end of the iteration. Notice the semicolon after the while condition; it is required in the syntax of a do-while loop.
A do-while loop is useful when an operation must happen at least once before the program decides whether to repeat it. Examples include displaying a menu before asking whether the user wants to continue or prompting for input before validating whether another attempt is required.
string? input;
do
{
Console.Write("Enter your name: ");
input = Console.ReadLine();
}
while (string.IsNullOrWhiteSpace(input));
Console.WriteLine($"Hello, {input}!");
The prompt appears at least once. If the user enters an empty string or only whitespace, the program asks again. If the user enters a valid name, the condition becomes false and the loop ends. This example assumes a console application where another input attempt is appropriate; production programs should also consider cancellation and end-of-input behavior.
4. The foreach Loop
The foreach loop is designed to process each element in a collection or another enumerable sequence. It is particularly useful for arrays, lists, sets, dictionaries, and many other types that support enumeration.
string[] languages =
{
"C#",
"Python",
"JavaScript"
};
foreach (string language in languages)
{
Console.WriteLine($"Learning {language}");
}
On each iteration, the loop variable receives the next element from the collection. The body executes until the sequence has no more elements. You do not need to manage an index or explicitly check the collection length.
This makes foreach a good choice when you want to perform the same operation on every item. For example, you could display every course in a learning platform, calculate a total from a collection of prices, or validate all records returned by an API.
var courses = new List<string>
{
"C#",
"ASP.NET Core",
"SQL"
};
foreach (string course in courses)
{
Console.WriteLine($"Course: {course}");
}
The same iteration approach works with both arrays and lists. If you need the numeric position of each item, you can use an indexed for loop or iterate with an index explicitly. Remember that modifying the structure of a standard collection during its foreach enumeration can invalidate the enumerator and cause an exception.
5. Understanding Loop Execution
Understanding the execution order helps you avoid off-by-one errors and incorrect results. Consider this example:
for (int i = 0; i < 3; i++)
{
Console.WriteLine(i);
}
The output is 0, 1, and 2. The loop starts at zero, so the condition i < 3 permits three iterations. After printing 2, the variable increases to 3. The condition then becomes false, and the loop terminates.
Compare that with i <= 3, which permits one additional iteration. The difference between < and <= is a common source of off-by-one errors. When working with arrays, remember that valid indexes start at zero and end at Length - 1.
You should also understand the scope of the loop variable. A variable declared in a for loop's initialization section, such as int i, is scoped to the loop statement. Variables declared before the loop remain accessible after it, subject to their enclosing scope.
6. break and continue
C# provides break and continue to control loop execution. The break statement immediately terminates the nearest enclosing loop. The continue statement skips the remaining statements in the current iteration and moves to the next iteration.
Use break when the required result has been found or when no further processing is necessary. In the following example, the loop stops as soon as it encounters the target number.
int[] numbers = { 10, 20, 30, 40, 50 };
foreach (int number in numbers)
{
if (number == 30)
{
Console.WriteLine("Target found.");
break;
}
Console.WriteLine(number);
}
The program prints 10 and 20, then prints the target message and exits the loop. The values 40 and 50 are never processed.
Use continue when you want to ignore certain elements but continue processing the remaining collection.
for (int i = 1; i <= 5; i++)
{
if (i == 3)
{
continue;
}
Console.WriteLine(i);
}
This loop prints 1, 2, 4, and 5. When i equals 3, the current iteration ends without printing the value. In a for loop, the iteration expression still executes after continue, so i increases normally.
In a while loop, ensure that a continue path does not accidentally skip the statement responsible for updating the condition variable. Otherwise, the loop may never finish.
7. Nested Loops
A nested loop is a loop placed inside another loop. For every iteration of the outer loop, the inner loop runs according to its own condition. Nested loops are useful for processing grids, generating tables, comparing elements, and handling two-dimensional data.
for (int row = 1; row <= 3; row++)
{
for (int column = 1; column <= 3; column++)
{
Console.Write($"{row},{column} ");
}
Console.WriteLine();
}
The outer loop controls the rows, and the inner loop controls the columns. The inner loop completes all three iterations before the outer loop advances to its next row. Together, the two loops produce nine row-and-column combinations.
Nested loops can become expensive as input sizes increase. If an outer loop runs n times and an inner loop runs m times for each outer iteration, the body executes approximately n × m times. When both loops depend on the same input size, the work may grow quadratically. Consider a more efficient algorithm when processing large datasets.
8. Looping Through Data with an Index
A foreach loop is ideal when you only need each element. An indexed for loop is more appropriate when the position itself matters, such as when displaying leaderboard ranks or replacing values at particular indexes.
string[] players = { "Alex", "Rhea", "Zed" };
for (int i = 0; i < players.Length; i++)
{
Console.WriteLine($"{i + 1}. {players[i]}");
}
The output includes positions 1, 2, and 3 even though the array indexes are 0, 1, and 2. Adding one to the index is appropriate for display because people generally expect rankings to start at first place rather than zero.
When iterating over an array or list, use the collection's Length or Count property as the loop boundary instead of hardcoding the number of elements. This keeps the loop correct when the collection changes.
9. Choosing the Right Loop
Although all four loop types repeat code, they are not interchangeable in every situation. Choosing the right one makes your intent easier to understand and reduces the chance of mistakes.
- for: Use when you need explicit index control, a counting sequence, or a known iteration range.
- while: Use when repetition depends on a condition that is checked before each iteration.
- do-while: Use when the operation must run at least once before the condition is evaluated.
- foreach: Use when you need to process every item in an array, list, or enumerable collection without manually managing indexes.
For example, use for to print numbers from 1 to 100, while to repeat a task until a condition changes, do-while to display a menu before checking whether it should appear again, and foreach to display all courses in a collection.
Do not choose a loop based only on how short its syntax looks. Prefer the structure that best represents the operation. Clear intent is more valuable than squeezing a loop into the smallest possible number of lines.
10. Common Loop Mistakes
- Creating an infinite loop: Ensure that the loop condition can eventually become false or that a deliberate exit path exists.
- Using the wrong boundary: Check whether the condition should use
<or<=to prevent missing or extra iterations. - Forgetting to update a counter: If a
whileloop depends on a counter, make sure the counter changes along every relevant execution path. - Accessing an invalid index: When using arrays or lists, keep indexes within the valid range.
- Modifying a collection during foreach: Structural modifications can invalidate a collection's enumerator. Use a suitable alternative when items must be removed or added during processing.
- Using unnecessary nested loops: Nested loops may increase processing time substantially for large collections.
- Using break or continue without considering control flow: Make sure early exits and skipped iterations do not prevent required updates or cleanup.
When debugging a loop, inspect the initial variable values, continuation condition, update operation, and expected number of iterations. Test edge cases such as an empty collection, a single element, and a condition that is initially false. These simple checks can reveal common errors quickly.
11. Best Practices for Writing Loops
Keep loop bodies focused on one clear responsibility. Use descriptive variable names such as index, attempts, or course instead of names that hide the variable's purpose. Use foreach when you do not need an index, and avoid unnecessary work inside a loop when it can be performed once before iteration.
Make termination conditions explicit and easy to follow. For long-running operations, consider cancellation and appropriate limits. Avoid repeatedly querying expensive external resources inside a loop unless necessary, and measure performance before optimizing otherwise clear code.
When a loop becomes complicated, extract the operation into a method or use suitable collection-processing tools such as LINQ. However, LINQ is not automatically better than a loop; choose it when it makes filtering, sorting, or transformation easier to understand.
12. Summary
Loops allow C# programs to repeat operations efficiently. The for loop offers explicit control over iteration, while repeats while a condition remains true, do-while executes at least once, and foreach processes elements in a collection. You can also use break to exit early and continue to skip the remainder of an iteration.
Practise by printing number sequences, calculating totals, processing an array of scores, displaying a leaderboard, and validating user input. Learn to recognize boundary conditions and termination rules so your loops behave correctly with both ordinary and unusual input.
For related concepts, explore conditional statements in C# to understand how decisions control program execution, and review arrays and lists to practise iterating through collections.