Loops let you execute the same block of code repeatedly — iterating over a list of items, processing each record in a database result, or building output from a collection. C# has four loop constructs, and the two you will use most often are for (index-based, full counter control) and foreach (clean iteration over any collection). In production ASP.NET Core code, LINQ methods often replace explicit loops for data transformation, but understanding loops is essential for understanding what LINQ does under the hood.
The For Loop
// Syntax: for (initialiser; condition; iterator)
for (int i = 0; i < 5; i++)
Console.Write($"{i} "); // 0 1 2 3 4
// Iterating an array with index
string[] fruits = { "Apple", "Banana", "Cherry" };
for (int i = 0; i < fruits.Length; i++)
Console.WriteLine($"[{i}] {fruits[i]}");
// [0] Apple
// [1] Banana
// [2] Cherry
// Reverse iteration
for (int i = fruits.Length - 1; i >= 0; i--)
Console.Write(fruits[i] + " "); // Cherry Banana Apple
// Step by 2
for (int i = 0; i <= 10; i += 2)
Console.Write($"{i} "); // 0 2 4 6 8 10
// Nested for — e.g. multiplication table
for (int r = 1; r <= 3; r++)
{
for (int c = 1; c <= 3; c++)
Console.Write($"{r * c,4}");
Console.WriteLine();
}
// 1 2 3
// 2 4 6
// 3 6 9
Note: The
for loop’s three parts are all optional. for (;;) is an infinite loop (same as while (true)). You can declare multiple variables in the initialiser: for (int i = 0, j = 10; i < j; i++, j--). The iterator expression can be any valid statement — i++, i += 2, i--. In practice, the standard for (int i = 0; i < n; i++) form covers the vast majority of use cases — stick to it unless you have a specific reason to vary.Tip: Use
for when you need the index (to access neighbouring elements, modify the array in place, or iterate in reverse). Use foreach for everything else — it is more readable, impossible to get an off-by-one error, and works on any IEnumerable<T> including database query results, LINQ projections, and async streams. In ASP.NET Core controller methods, foreach over a list of DTOs to build response models is the idiomatic pattern.Warning: Never modify a collection while iterating it with
foreach — it throws an InvalidOperationException with the message “Collection was modified; enumeration operation may not execute.” If you need to remove items while iterating, iterate backwards with a for loop and remove by index, or use LINQ’s .Where() to build a new filtered collection and assign it back. This is a very common bug for developers new to C#.The Foreach Loop
// Works on any IEnumerable<T> — arrays, List<T>, LINQ queries, etc.
string[] fruits = { "Apple", "Banana", "Cherry" };
foreach (string fruit in fruits)
Console.WriteLine(fruit);
// With a List<T>
var numbers = new List<int> { 10, 20, 30, 40, 50 };
int sum = 0;
foreach (int n in numbers)
sum += n;
Console.WriteLine($"Sum: {sum}"); // Sum: 150
// foreach with index using LINQ
foreach ((int index, string fruit) in fruits.Select((f, i) => (i, f)))
Console.WriteLine($"[{index}] {fruit}");
// break — exit the loop early
foreach (int n in numbers)
{
if (n == 30) break; // stops when n is 30
Console.Write($"{n} "); // 10 20
}
// continue — skip the current iteration
foreach (int n in numbers)
{
if (n % 20 == 0) continue; // skip multiples of 20
Console.Write($"{n} "); // 10 30 50
}
Break and Continue
| Keyword | Effect | Works In |
|---|---|---|
break |
Exits the current loop immediately | for, foreach, while, do-while, switch |
continue |
Skips the rest of the current iteration, goes to next | for, foreach, while, do-while |
return |
Exits the entire method (and therefore the loop) | Any loop inside a method |
Common Mistakes
Mistake 1 — Modifying a collection inside foreach (InvalidOperationException)
❌ Wrong:
var items = new List<int> { 1, 2, 3, 4 };
foreach (int item in items)
if (item % 2 == 0) items.Remove(item); // InvalidOperationException!
✅ Correct — use LINQ to build a new collection:
items = items.Where(x => x % 2 != 0).ToList(); // ✓ filters without mutating during iteration
Mistake 2 — Off-by-one in the for loop condition
❌ Wrong — i <= array.Length throws IndexOutOfRangeException on last iteration.
✅ Correct — always use i < array.Length.