Easy Learn C#

C# Loops

Introduction to Loops

Loops are control structures that allow you to execute a block of code repeatedly. They are essential for automating repetitive tasks, processing collections of data, and implementing iterative algorithms. C# provides several types of loops to suit different programming needs.

Key Loop Concepts:

  • Loops execute a code block multiple times
  • Iteration variables track the progress of the loop
  • Loop conditions determine when to stop
  • Break and continue statements provide additional control
  • The right loop type depends on your specific use case

For Loop

The for loop is ideal when you know exactly how many times you want to repeat a block of code. It combines initialization, condition, and iteration into a single statement.

For Loop Syntax:


for (initialization; condition; iteration)
{
    // Code to execute in each iteration
}
                            

The three parts of a for loop:

  • Initialization: Executes once before the loop starts (usually to declare and initialize a counter variable)
  • Condition: Evaluated before each iteration; the loop continues as long as it's true
  • Iteration: Executes after each iteration (usually to update the counter variable)

For Loop Examples:


// Basic for loop counting from 0 to 4
for (int i = 0; i < 5; i++)
{
    Console.WriteLine($"Iteration {i}");
}
// Output:
// Iteration 0
// Iteration 1
// Iteration 2
// Iteration 3
// Iteration 4

// Counting down
for (int i = 10; i > 0; i--)
{
    Console.WriteLine($"Countdown: {i}");
}

// Custom iteration steps
for (int i = 0; i <= 20; i += 2)
{
    Console.WriteLine($"Even number: {i}");
}

// Multiple loop variables
for (int i = 1, j = 10; i <= 10 && j >= 1; i++, j--)
{
    Console.WriteLine($"i = {i}, j = {j}");
}
                            

For Loop Applications:


// Summing numbers
int sum = 0;
for (int i = 1; i <= 100; i++)
{
    sum += i;
}
Console.WriteLine($"Sum of 1 to 100: {sum}");  // 5050

// Processing array elements
int[] numbers = { 10, 20, 30, 40, 50 };
for (int i = 0; i < numbers.Length; i++)
{
    Console.WriteLine($"Element at index {i}: {numbers[i]}");
}

// Building a string pattern
string pattern = "";
for (int i = 1; i <= 5; i++)
{
    // Append i asterisks to the pattern
    for (int j = 0; j < i; j++)
    {
        pattern += "*";
    }
    pattern += "\n";  // Add a new line
}
Console.WriteLine(pattern);
// Output:
// *
// **
// ***
// ****
// *****
                            

While Loop

The while loop continues executing a block of code as long as a specified condition remains true. It's ideal when you don't know in advance how many iterations will be needed.

While Loop Syntax:


while (condition)
{
    // Code to execute as long as condition is true
}
                            

Key characteristics of while loops:

  • The condition is evaluated before each iteration
  • If the condition is initially false, the loop body never executes
  • The loop continues until the condition becomes false
  • Variables used in the condition must be initialized before the loop

While Loop Examples:


// Basic while loop
int count = 0;
while (count < 5)
{
    Console.WriteLine($"Count: {count}");
    count++;
}

// Processing input until a condition is met
Console.WriteLine("Enter numbers to sum (enter 0 to finish):");
int number;
int sum = 0;

// Read the first number
number = Convert.ToInt32(Console.ReadLine());

while (number != 0)
{
    sum += number;
    // Read the next number
    number = Convert.ToInt32(Console.ReadLine());
}

Console.WriteLine($"Sum: {sum}");

// Random number guessing game
Random random = new Random();
int targetNumber = random.Next(1, 101);  // Random number between 1 and 100
int guess = 0;
int attempts = 0;

Console.WriteLine("Guess a number between 1 and 100:");

while (guess != targetNumber)
{
    guess = Convert.ToInt32(Console.ReadLine());
    attempts++;
    
    if (guess < targetNumber)
    {
        Console.WriteLine("Too low! Try again.");
    }
    else if (guess > targetNumber)
    {
        Console.WriteLine("Too high! Try again.");
    }
}

Console.WriteLine($"Correct! You guessed it in {attempts} attempts.");
                            

Do-While Loop

The do-while loop is similar to the while loop, but it checks the condition after executing the loop body. This ensures that the loop body executes at least once, regardless of the condition.

Do-While Loop Syntax:


do
{
    // Code to execute at least once and then as long as condition is true
} while (condition);
                            

Key differences from while loop:

  • The condition is evaluated after each iteration
  • The loop body executes at least once, even if the condition is initially false
  • Useful when you want to ensure at least one execution of the loop body

Do-While Loop Examples:


// Basic do-while loop
int count = 0;
do
{
    Console.WriteLine($"Count: {count}");
    count++;
} while (count < 5);

// Menu-driven program
int choice;
do
{
    Console.WriteLine("\nMenu Options:");
    Console.WriteLine("1. Display greeting");
    Console.WriteLine("2. Display date and time");
    Console.WriteLine("3. Exit");
    Console.Write("Enter your choice (1-3): ");
    
    choice = Convert.ToInt32(Console.ReadLine());
    
    switch (choice)
    {
        case 1:
            Console.WriteLine("Hello, world!");
            break;
        case 2:
            Console.WriteLine($"Current date and time: {DateTime.Now}");
            break;
        case 3:
            Console.WriteLine("Exiting program...");
            break;
        default:
            Console.WriteLine("Invalid choice. Please try again.");
            break;
    }
} while (choice != 3);

// Input validation
string password;
do
{
    Console.Write("Enter a password (at least 8 characters): ");
    password = Console.ReadLine();
    
    if (password.Length < 8)
    {
        Console.WriteLine("Password is too short!");
    }
} while (password.Length < 8);

Console.WriteLine("Password accepted.");
                            

Foreach Loop

The foreach loop is designed specifically for iterating through collections like arrays, lists, and other enumerable types. It's simpler and safer than using a for loop when you want to process each element.

Foreach Loop Syntax:


foreach (type variable in collection)
{
    // Code to process each element
}
                            

Key characteristics of foreach loops:

  • Automatically iterates through all elements in a collection
  • Provides a read-only variable for each element during iteration
  • Handles the iteration details for you (no need to track indices)
  • Works with any collection that implements the IEnumerable interface

Foreach Loop Examples:


// Iterating through an array
int[] numbers = { 1, 2, 3, 4, 5 };
foreach (int number in numbers)
{
    Console.WriteLine($"Number: {number}");
}

// Iterating through a string (character by character)
string message = "Hello";
foreach (char c in message)
{
    Console.WriteLine(c);
}

// Iterating through a List
List fruits = new List { "Apple", "Banana", "Cherry", "Date" };
foreach (string fruit in fruits)
{
    Console.WriteLine($"Fruit: {fruit}");
}

// Iterating through a Dictionary
Dictionary ages = new Dictionary
{
    { "Alice", 25 },
    { "Bob", 30 },
    { "Charlie", 35 }
};

foreach (KeyValuePair pair in ages)
{
    Console.WriteLine($"{pair.Key} is {pair.Value} years old");
}

// Or, more concisely with C# 7.0+ deconstruction:
foreach (var (name, age) in ages)
{
    Console.WriteLine($"{name} is {age} years old");
}
                            

Foreach Loop Limitations:


// You can't modify the collection while iterating with foreach
List numbers = new List { 1, 2, 3, 4, 5 };

// This will throw an exception:
foreach (int number in numbers)
{
    // The following line would cause an error:
    // numbers.Remove(number);  // Invalid operation!
}

// You can't modify the iteration variable
string[] names = { "Alice", "Bob", "Charlie" };
foreach (string name in names)
{
    // The following line would cause an error:
    // name = name.ToUpper();  // Invalid operation!
    
    // Instead, you can only read the value:
    Console.WriteLine(name.ToUpper());
}
                            

To modify elements during iteration, use a for loop with an index instead:


// Using for loop when you need to modify elements
string[] words = { "apple", "banana", "cherry" };
for (int i = 0; i < words.Length; i++)
{
    words[i] = words[i].ToUpper();
}

// Now all elements are uppercase
foreach (string word in words)
{
    Console.WriteLine(word);  // APPLE, BANANA, CHERRY
}
                                

Nested Loops

A nested loop is a loop within another loop. This structure is useful for working with multi-dimensional data or generating complex patterns.

Nested Loop Examples:


// Multiplication table
for (int i = 1; i <= 10; i++)
{
    for (int j = 1; j <= 10; j++)
    {
        Console.Write($"{i * j,4}");  // The ,4 adds padding for alignment
    }
    Console.WriteLine();  // New line after each row
}

// Pattern printing
for (int i = 1; i <= 5; i++)
{
    // Print spaces
    for (int j = 5; j > i; j--)
    {
        Console.Write(" ");
    }
    // Print stars
    for (int k = 1; k <= (2 * i - 1); k++)
    {
        Console.Write("*");
    }
    Console.WriteLine();
}
// Output:
//     *
//    ***
//   *****
//  *******
// *********

// Working with a 2D array
int[,] matrix = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 }
};

// Print all elements of the 2D array
for (int row = 0; row < 3; row++)
{
    for (int col = 0; col < 3; col++)
    {
        Console.Write($"{matrix[row, col]} ");
    }
    Console.WriteLine();
}
                            

Performance considerations for nested loops:

  • Each level of nesting multiplies the number of iterations
  • Avoid deep nesting when possible (more than 3 levels can be hard to follow)
  • For better performance, put the larger loop on the outside when possible

Loop Control Statements

C# provides special statements to control the flow of loops: break, continue, and goto.

Break Statement:


// Break terminates the innermost loop
for (int i = 1; i <= 10; i++)
{
    if (i == 5)
    {
        break;  // Exit the loop when i equals 5
    }
    Console.WriteLine(i);
}
// Output: 1, 2, 3, 4

// Break in a nested loop (exits only the innermost loop)
for (int i = 1; i <= 3; i++)
{
    Console.WriteLine($"Outer loop: {i}");
    
    for (int j = 1; j <= 3; j++)
    {
        if (i == 2 && j == 2)
        {
            break;  // Exit the inner loop when i=2 and j=2
        }
        Console.WriteLine($"  Inner loop: {j}");
    }
}

// Finding an element in an array
int[] numbers = { 10, 20, 30, 40, 50 };
int searchValue = 30;
bool found = false;

for (int i = 0; i < numbers.Length; i++)
{
    if (numbers[i] == searchValue)
    {
        Console.WriteLine($"Found {searchValue} at index {i}");
        found = true;
        break;  // No need to continue searching
    }
}

if (!found)
{
    Console.WriteLine($"{searchValue} not found in the array");
}
                            

Continue Statement:


// Continue skips the rest of the current iteration
for (int i = 1; i <= 10; i++)
{
    if (i % 2 == 0)
    {
        continue;  // Skip even numbers
    }
    Console.WriteLine(i);  // Only prints odd numbers: 1, 3, 5, 7, 9
}

// Skipping specific values
string[] words = { "apple", null, "banana", "", "cherry", null };
foreach (string word in words)
{
    if (string.IsNullOrEmpty(word))
    {
        continue;  // Skip null or empty strings
    }
    Console.WriteLine($"Word: {word}");
}

// Processing only valid records
List data = new List { 10, -5, 0, 25, -3, 12 };
int sum = 0;

foreach (int value in data)
{
    if (value <= 0)
    {
        continue;  // Skip non-positive values
    }
    sum += value;
}

Console.WriteLine($"Sum of positive values: {sum}");  // 47
                            

Labeled Statements and Goto:


// Using goto with a label to exit nested loops
for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 3; j++)
    {
        if (i == 1 && j == 1)
        {
            goto LoopExit;  // Exit both loops
        }
        Console.WriteLine($"i = {i}, j = {j}");
    }
}
LoopExit:
Console.WriteLine("Exited both loops");

// Note: While goto exists in C#, it's generally recommended to avoid using it 
// in favor of more structured approaches like methods and return statements.
                            

Alternative to goto for exiting nested loops:


// Better approach - use a flag variable
bool shouldExit = false;
for (int i = 0; i < 3 && !shouldExit; i++)
{
    for (int j = 0; j < 3 && !shouldExit; j++)
    {
        if (i == 1 && j == 1)
        {
            shouldExit = true;  // Signal to exit both loops
            break;
        }
        Console.WriteLine($"i = {i}, j = {j}");
    }
}
Console.WriteLine("Exited both loops");

// Even better - extract the nested loops into a method and use return
void ProcessMatrix()
{
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            if (i == 1 && j == 1)
            {
                return;  // Exit the method and both loops
            }
            Console.WriteLine($"i = {i}, j = {j}");
        }
    }
}

ProcessMatrix();
Console.WriteLine("Exited both loops");
                                

Infinite Loops

An infinite loop is a loop that continues indefinitely because its termination condition is never satisfied. While usually undesirable, infinite loops can sometimes be useful when combined with a break statement or in certain types of programs like servers and game loops.

Creating and Controlling Infinite Loops:


// Intentional infinite loop with for
for (;;)
{
    Console.WriteLine("This will run forever unless broken");
    // Some code that eventually breaks the loop
    if (DateTime.Now.Second % 10 == 0)
    {
        break;
    }
}

// Infinite loop with while
while (true)
{
    Console.WriteLine("Press 'q' to quit");
    string input = Console.ReadLine();
    if (input.ToLower() == "q")
    {
        break;
    }
}

// Game loop example
bool isGameRunning = true;
while (isGameRunning)
{
    // Process input
    ProcessInput();
    
    // Update game state
    UpdateGame();
    
    // Render graphics
    RenderGame();
    
    // Check if game should end
    if (GameOver())
    {
        isGameRunning = false;
    }
}

// Event processing loop
while (true)
{
    // Wait for the next event
    Event nextEvent = WaitForEvent();
    
    // Process the event
    ProcessEvent(nextEvent);
    
    // Check for exit condition
    if (nextEvent.Type == EventType.Shutdown)
    {
        break;
    }
}
                            

Avoiding accidental infinite loops:

  • Ensure loop conditions will eventually become false
  • Double-check counter updates in for/while loops
  • Be careful with floating-point comparisons in loop conditions
  • Always include a way to exit intentional infinite loops

Loop Efficiency and Best Practices

Writing efficient and maintainable loops is important, especially when dealing with large data sets or performance-critical code.

Loop Optimization Tips:


// DO: Cache the collection length/count outside the loop
int[] numbers = new int[10000];
int length = numbers.Length;  // Cache the length
for (int i = 0; i < length; i++)
{
    // Process numbers[i]
}

// DON'T: Recalculate length on each iteration
for (int i = 0; i < numbers.Length; i++)  // Less efficient
{
    // Process numbers[i]
}

// DO: Avoid unnecessary method calls in the loop
string[] names = { "Alice", "Bob", "Charlie" };
string searchName = "Bob";
bool found = false;

// Convert to lowercase once, outside the loop
searchName = searchName.ToLower();
foreach (string name in names)
{
    if (name.ToLower() == searchName)
    {
        found = true;
        break;
    }
}

// DO: Consider using LINQ for cleaner, more readable code
// (though sometimes with a slight performance trade-off)
bool foundWithLinq = names.Any(name => name.ToLower() == searchName);

// DO: Prefer foreach over for when you don't need the index
List items = new List { "One", "Two", "Three" };

// Preferred when you don't need the index
foreach (string item in items)
{
    Console.WriteLine(item);
}

// Use for when you need the index
for (int i = 0; i < items.Count; i++)
{
    Console.WriteLine($"Item {i + 1}: {items[i]}");
}
                            

Loop Selection Guide:

Loop Type Best Used When
for You know exactly how many iterations you need
while You need to continue until a condition becomes false
do-while You need to execute the loop at least once regardless of the condition
foreach You want to iterate through all elements in a collection

Additional best practices:

  • Keep loops simple and focused on a single task
  • Consider extracting complex loop bodies into separate methods
  • Be mindful of performance when working with large datasets
  • Use appropriate loop constructs for the task at hand
  • Always provide a way to exit the loop (avoid infinite loops)