Continue Statement in C#
Loop control might sound simple, but it plays a big role in how clean, efficient and easy to understand your code is. Knowing when to skip an iteration, break out of a loop or rewrite your logic for clarity can make a huge difference in code quality. The continue statement is one such feature very useful when used correctly, but if overused or misused, it can make your code harder to read, introduce subtle bugs (especially in nested loops) and increase overall complexity.
What is the continue statement?
The continue statement in C# is a loop control keyword used to skip the remaining code in the current iteration of the innermost loop (the loop where it appears) and jump directly to the next iteration of that same loop.
It’s important to note that continue doesn’t break out of the loop that’s the job of the break statement. Instead, it keeps the loop running, just skipping certain parts of the code when a specific condition is met.
This makes continue a valuable tool for controlling loop flow efficiently while keeping your code clean and readable.
Why and When to Use the continue Statement?
The continue statement can be a powerful tool in your loop control toolkit. Here are some common scenarios where it’s beneficial to use:
1. Skip Unnecessary Processing
If you're iterating over a collection and want to filter out certain items that don’t meet a specific condition, continue allows you to skip those items without processing them. For example, you can skip empty or invalid values in a list and continue with the next one.
foreach (var item in items)
{
if (item == null) continue; // Skip null items
// Process valid item
}2. Improve Readability with Early Exit
Using continue allows you to exit an iteration early, which reduces the need for deep nesting of if statements. This can improve readability and make your code less indented and easier to follow.
for (int i = 0; i < 10; i++)
{
if (i % 2 == 0) continue; // Skip even numbers
// Process odd numbers
}3. Simplify Complex Nested Logic
When you have multiple conditions in a loop, continue can help avoid deeply nested else statements. Instead of nesting everything under an else block, you can simply skip the current iteration if a condition isn’t met, keeping your logic flatter and more understandable.
foreach (var item in items)
{
if (!item.IsValid()) continue; // Skip invalid items
// Process valid items
Console.WriteLine(item);
}4. Control Flow in Multi-Level Loops
In loops with multiple levels (like nested loops), continue allows you to skip only the innermost loop’s current iteration, without affecting the outer loops. This is useful when you need to control flow inside nested loops without disrupting the outer logic.
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
if (j == 3) continue; // Skip when j is 3, but keep outer loop going
Console.WriteLine($"i={i}, j={j}");
}
}Using continue with different loop types
The continue statement can be used with any type of loop in C# to skip the rest of the current iteration and proceed to the next iteration of the loop. Here’s how you can apply it with different types of loops in C# -
1. for loop
for (int i = 1; i <= 10; i++)
{
if (i % 2 == 0)
{
continue; // skip even numbers
}
Console.WriteLine(i); // prints only odd numbers
}Output: 1 3 5 7 9 Here, whenever i is even, the continue prevents the WriteLine and jumps to the next iteration.
2. while loop
int i = 0;
while (i < 10)
{
i++;
if (i == 5)
{
continue; // skip the rest when i == 5
}
Console.WriteLine(i);
}In this loop, when i equals 5, the continue skips Console.WriteLine for that iteration and the loop proceeds with i = 6.
3. do-while loop
int i = 0;
do
{
i++;
if (i == 3)
{
continue;
}
Console.WriteLine(i);
} while (i < 5);Here, when i == 3, continue jumps to the condition check and repeats, thus skipping the WriteLine for that value.
4. foreach loop
string[] names = { "Alice", "Bob", "Charlie", null, "Dave" };
foreach (var name in names)
{
if (name == null)
{
continue; // skip null entries
}
Console.WriteLine(name);
}Using continue in foreach allows you to filter out items inline, before performing operations on each element.
Continue statement with nested loop
In the case of nested loops, the continue statement only affects the innermost loop in which it is placed. This means if you use continue inside a nested loop, it will only skip the current iteration of that specific inner loop and continue with the next iteration of the inner loop, while the outer loops will continue their execution as usual.
Example 1
using System;
class Program
{
static void Main()
{
for(int i=1; i<=3; i++) {
Console.WriteLine($"outer loop i: {i}");
if(i==2) {
Console.WriteLine($"\tCONTINUE i: {i}");
continue;
}
for(int j=1; j<=3; j++) {
Console.WriteLine($"\tinner loop i: {i} j {j}");
}
}
}
}outer loop i: 1 inner loop i: 1 j 1 inner loop i: 1 j 2 inner loop i: 1 j 3 outer loop i: 2 CONTINUE i: 2 outer loop i: 3 inner loop i: 3 j 1 inner loop i: 3 j 2 inner loop i: 3 j 3
Example 2
using System;
class Program
{
static void Main()
{
for(int i=1; i<=3; i++) {
Console.WriteLine($"outer loop i: {i}");
for(int j=1; j<=3; j++) {
Console.WriteLine($"\tinner loop i: {i} j {j}");
if(j==2) {
Console.WriteLine($"\tCONTINUE i: {i} j {j}");
continue;
}
}
}
}
}outer loop i: 1 inner loop i: 1 j 1 inner loop i: 1 j 2 CONTINUE i: 1 j 2 inner loop i: 1 j 3 outer loop i: 2 inner loop i: 2 j 1 inner loop i: 2 j 2 CONTINUE i: 2 j 2 inner loop i: 2 j 3 outer loop i: 3 inner loop i: 3 j 1 inner loop i: 3 j 2 CONTINUE i: 3 j 2 inner loop i: 3 j 3
Example 3
using System;
class Program
{
static void Main()
{
for(int i=1; i<=2; i++) {
Console.WriteLine($"outer loop i: {i}");
for(int j=1; j<=3; j++) {
Console.WriteLine($"\tinner loop i: {i} j {j}");
if(j==2){
Console.WriteLine($"\tCONTINUE i: {i} j {j}");
continue;
}
for(int k=1;k<=3;k++){
Console.WriteLine($"\t\t2nd inner loop i: {i} j {j} k {k}");
}
}
}
}
}outer loop i: 1 inner loop i: 1 j 1 2nd inner loop i: 1 j 1 k 1 2nd inner loop i: 1 j 1 k 2 2nd inner loop i: 1 j 1 k 3 inner loop i: 1 j 2 CONTINUE i: 1 j 2 inner loop i: 1 j 3 2nd inner loop i: 1 j 3 k 1 2nd inner loop i: 1 j 3 k 2 2nd inner loop i: 1 j 3 k 3 outer loop i: 2 inner loop i: 2 j 1 2nd inner loop i: 2 j 1 k 1 2nd inner loop i: 2 j 1 k 2 2nd inner loop i: 2 j 1 k 3 inner loop i: 2 j 2 CONTINUE i: 2 j 2 inner loop i: 2 j 3 2nd inner loop i: 2 j 3 k 1
Common pitfalls
Pitfall #1: Infinite loops
In a while or do‐while loop, if continue prevents the loop’s counter or condition from changing, you are creating risk of infinite loop
int i = 0;
while (i < 5)
{
if (someCondition)
{
continue; // i never increments — infinite loop
}
i++;
}Tip : Ensure the loop’s progression (increment, condition change) occurs regardless of a continue.
Pitfall #2: Readability vs cleverness
When the body of a loop contains too many continue (or break) statements combined with complex branching, the logic becomes harder to follow. Some developers argue that deeply nested or scattered control statements reduce clarity.
Rule of thumb : Keep your loops simple. If you find yourself using multiple continue statements with complicated conditions, it’s likely time to refactor the code into smaller, clearly named methods.
Pitfall #3: Skipping important code
When you place a continue statement early in a loop body, you may unintentionally skip cleanup logic, logging statements or critical increments, which can lead to subtle bugs or even infinite loops.
Problem Version - Unintentionally Skipping Cleanup / LoggingList<Item> items = GetItems();
int invalidCount = 0;
for (int i = 0; i < items.Count; i++)
{
if (!items[i].IsValid)
{
continue; // Skip invalid items - but we never increment invalidCount or log them!
}
items[i].Process();
// Suppose we also log successful processing here
Console.WriteLine($"Processed item at index {i}");
}List<Item> items = GetItems();
int invalidCount = 0;
for (int i = 0; i < items.Count; i++)
{
if (!items[i].IsValid)
{
invalidCount++; // Handle invalid item
Console.WriteLine($"Skipping invalid item at index {i}");
continue; // Then skip processing
}
items[i].Process();
Console.WriteLine($"Processed item at index {i}");
}
// After loop: we can report summary
Console.WriteLine($"Total invalid items skipped: {invalidCount}");Real-World Scenario: Batching work, skipping invalid items
Imagine you have a list of tasks to perform and you want to skip tasks marked as archived and log them separately, then continue processing the rest.
List<Task> tasks = GetPendingTasks();
foreach (var task in tasks)
{
if (task.IsArchived)
{
LogSkipped(task, reason: "Archived");
continue; // move to next task, skipping execution
}
if (!task.IsReady)
{
LogSkipped(task, reason: "Not Ready");
continue;
}
try
{
Execute(task);
LogSuccess(task);
}
catch(Exception ex)
{
LogFailure(task, ex);
}
}Here continue keeps the loop clean: invalid tasks are logged and skipped, real tasks are handled in the main block. This pattern helps readability and maintainability.
Key Points
- continue is a simple statement, but with powerful implications. it skips the rest of the current iteration and moves to the next one.
- It works in for, while, do…while and foreach loops.
- It affects only the innermost loop in which it appears.
- Good uses: early exit filtering, cleaner loop bodies, skipping invalid data, performance optimization.
- Pitfalls : skipping required cleanup/updates, readability issues with many continues, confusion in nested loops, infinite loops in while/do when updates are skipped.
- Best practices: use early at top of loop for invalid cases, keep the rest of loop body focused, document intent, avoid over-use, always ensure loop progression.
- Using continue wisely can improve both the performance and clarity of your loop logic. But like any powerful tool, it deserves careful use rather than being thrown in without thought.
- Don't use continue If using continue forces you to add more if/else blocks or makes the loop harder.
- Use continue at the top of a loop to filter out undesired cases.
