C# Iteration
Introduction
Iteration is a fundamental concept in programming that allows us to process each element in a collection one by one. In C#, there are several ways to iterate through collections like arrays, lists, dictionaries, and other data structures. Mastering iteration techniques is essential for effectively working with collections and implementing common algorithms.
In this tutorial, we'll explore the various iteration methods available in C#, from basic loops to more advanced LINQ-based approaches, helping you understand when and how to use each technique.
Basic Iteration Techniques
The foreach
Loop
The foreach
loop is the most straightforward way to iterate through any collection that implements the IEnumerable
interface (which includes most C# collections).
// Iterating through an array of strings
string[] fruits = { "Apple", "Banana", "Cherry", "Date", "Elderberry" };
Console.WriteLine("Fruits in my basket:");
foreach (string fruit in fruits)
{
Console.WriteLine($"- {fruit}");
}
Output:
Fruits in my basket:
- Apple
- Banana
- Cherry
- Date
- Elderberry
The foreach
loop automatically handles the details of traversing the collection, making it clean and easy to read. It works with arrays, lists, dictionaries, and any other collection that implements IEnumerable
.
The for
Loop
When you need more control over the iteration, such as accessing elements by index or skipping elements, the for
loop is a good choice:
// Using a for loop to iterate through a List
List<int> numbers = new List<int> { 10, 20, 30, 40, 50 };
Console.WriteLine("Displaying numbers with their indices:");
for (int i = 0; i < numbers.Count; i++)
{
Console.WriteLine($"Index {i}: {numbers[i]}");
}
Output:
Displaying numbers with their indices:
Index 0: 10
Index 1: 20
Index 2: 30
Index 3: 40
Index 4: 50
The for
loop is particularly useful when:
- You need to know the current index
- You want to iterate in reverse order
- You need to skip elements or have a non-standard increment
The while
and do-while
Loops
These loops are useful when the number of iterations isn't known in advance:
// Using a while loop with a queue
Queue<string> taskQueue = new Queue<string>();
taskQueue.Enqueue("Send email");
taskQueue.Enqueue("Generate report");
taskQueue.Enqueue("Update database");
Console.WriteLine("Processing tasks:");
while (taskQueue.Count > 0)
{
string currentTask = taskQueue.Dequeue();
Console.WriteLine($"Processing: {currentTask}");
}
Output:
Processing tasks:
Processing: Send email
Processing: Generate report
Processing: Update database
Iterating Different Collection Types
Iterating Through Dictionaries
Dictionaries store key-value pairs, and there are several ways to iterate through them:
Dictionary<string, int> ages = new Dictionary<string, int>
{
{ "Alice", 25 },
{ "Bob", 30 },
{ "Charlie", 35 }
};
// Method 1: Iterating through KeyValuePair objects
Console.WriteLine("People and their ages:");
foreach (KeyValuePair<string, int> person in ages)
{
Console.WriteLine($"{person.Key} is {person.Value} years old");
}
// Method 2: Iterating through keys
Console.WriteLine("\nJust the names:");
foreach (string name in ages.Keys)
{
Console.WriteLine(name);
}
// Method 3: Iterating through values
Console.WriteLine("\nJust the ages:");
foreach (int age in ages.Values)
{
Console.WriteLine(age);
}
Output:
People and their ages:
Alice is 25 years old
Bob is 30 years old
Charlie is 35 years old
Just the names:
Alice
Bob
Charlie
Just the ages:
25
30
35
Iterating Through Multi-dimensional Arrays
C# supports multi-dimensional arrays, and iteration requires nested loops:
// Creating a 2D array (3x3 matrix)
int[,] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Console.WriteLine("Matrix contents:");
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
Console.Write($"{matrix[row, col]} ");
}
Console.WriteLine(); // New line after each row
}
Output:
Matrix contents:
1 2 3
4 5 6
7 8 9
Advanced Iteration Techniques
LINQ-based Iteration
LINQ (Language Integrated Query) provides powerful methods for collection manipulation and traversal:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Using ForEach with a lambda expression
Console.WriteLine("All numbers:");
numbers.ForEach(num => Console.Write($"{num} "));
Console.WriteLine();
// Using Where to filter, then iterate
Console.WriteLine("\nEven numbers using LINQ:");
IEnumerable<int> evenNumbers = numbers.Where(n => n % 2 == 0);
foreach (int num in evenNumbers)
{
Console.Write($"{num} ");
}
Console.WriteLine();
Output:
All numbers:
1 2 3 4 5 6 7 8 9 10
Even numbers using LINQ:
2 4 6 8 10
Using Iterators with yield return
C# allows you to create custom iterators using the yield return
statement:
// A method that generates Fibonacci numbers
static IEnumerable<int> Fibonacci(int count)
{
int current = 0;
int next = 1;
for (int i = 0; i < count; i++)
{
yield return current;
int temp = current;
current = next;
next = temp + next;
}
}
// Using our custom iterator
Console.WriteLine("First 10 Fibonacci numbers:");
foreach (int num in Fibonacci(10))
{
Console.Write($"{num} ");
}
Console.WriteLine();
Output:
First 10 Fibonacci numbers:
0 1 1 2 3 5 8 13 21 34
Real-world Applications
Processing Data Records
Here's a practical example of processing a collection of customer data:
// Define a simple Customer class
public class Customer
{
public string Name { get; set; }
public string Email { get; set; }
public decimal TotalPurchases { get; set; }
}
// In your main program
List<Customer> customers = new List<Customer>
{
new Customer { Name = "Alice Johnson", Email = "[email protected]", TotalPurchases = 1250.50m },
new Customer { Name = "Bob Smith", Email = "[email protected]", TotalPurchases = 750.25m },
new Customer { Name = "Charlie Brown", Email = "[email protected]", TotalPurchases = 3200.00m },
new Customer { Name = "Diana Williams", Email = "[email protected]", TotalPurchases = 450.75m }
};
// Finding premium customers (those who spent over $1000)
Console.WriteLine("Premium Customers:");
foreach (Customer customer in customers)
{
if (customer.TotalPurchases > 1000)
{
Console.WriteLine($"{customer.Name} ({customer.Email}) - ${customer.TotalPurchases}");
}
}
// Calculate the total revenue
decimal totalRevenue = 0;
foreach (Customer customer in customers)
{
totalRevenue += customer.TotalPurchases;
}
Console.WriteLine($"\nTotal Revenue: ${totalRevenue}");
// Same calculation using LINQ
decimal linqTotalRevenue = customers.Sum(c => c.TotalPurchases);
Console.WriteLine($"Total Revenue (LINQ): ${linqTotalRevenue}");
Output:
Premium Customers:
Alice Johnson ([email protected]) - $1250.50
Charlie Brown ([email protected]) - $3200.00
Total Revenue: $5651.50
Total Revenue (LINQ): $5651.50
Building a Simple File Processing Utility
This example shows how to iterate through files in a directory:
// Simulate finding and processing log files
string[] logFiles = {
"system_20230101.log",
"system_20230102.log",
"app_errors_20230101.log",
"app_errors_20230102.log",
"access_20230101.log"
};
// Filter and process only system logs
Console.WriteLine("Processing system logs:");
foreach (string file in logFiles)
{
if (file.StartsWith("system_"))
{
Console.WriteLine($"Processing file: {file}");
// In a real application, you would open and read the file here
}
}
// Using LINQ to find specific log files
Console.WriteLine("\nLogs from January 1, 2023:");
var jan1Logs = logFiles.Where(file => file.Contains("20230101"));
foreach (string file in jan1Logs)
{
Console.WriteLine(file);
}
Output:
Processing system logs:
Processing file: system_20230101.log
Processing file: system_20230102.log
Logs from January 1, 2023:
system_20230101.log
app_errors_20230101.log
access_20230101.log
Performance Considerations
Different iteration methods have different performance characteristics:
foreach
is generally the most readable and sufficient for most casesfor
can be slightly faster when working with arrays and indexed collections- LINQ methods can be very expressive but might introduce slight overhead
- Avoid modifying collections while iterating through them to prevent errors
Summary
In this tutorial, we've covered the various ways to iterate through collections in C#:
- Basic loops:
foreach
,for
,while
- Collection-specific iteration techniques for arrays, lists, dictionaries
- Advanced techniques using LINQ and custom iterators
- Real-world applications demonstrating practical uses of iteration
Mastering these iteration techniques will help you write cleaner, more efficient code when working with collections. As you gain experience, you'll develop an intuition for which approach is best for each situation.
Exercises
- Create a program that counts the frequency of each word in a text string using a dictionary.
- Write a method that takes a list of integers and returns a new list containing only the prime numbers.
- Implement a custom iterator that generates the first n square numbers.
- Create a program that reads a CSV file and processes each row using appropriate iteration techniques.
- Write a method that finds the intersection of two lists (elements that appear in both lists) without using LINQ.
Additional Resources
- C# Documentation on foreach statement
- LINQ Overview
- C# Iterators
- Performance Tips for C# Collections
Keep practicing with different types of collections and iteration techniques to build your confidence and proficiency with C# collections!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)