C# List – foreach and List.ForEach()
In C#, a List<T> can be processed item by item in two common ways: the foreach statement and the List<T>.ForEach() method. They look similar, but they are different language features and offer different control-flow options.
The spelling also matters: foreach is the C# iteration keyword, while ForEach() is a method defined by List<T>. The foreach statement works with many enumerable collections, not only List<T>.
This tutorial shows both forms with numbers and objects, then explains lambda syntax, index-based iteration, loop control, and the practical differences between foreach and List.ForEach().
C# List.ForEach(Action<T>) syntax
List<T>.ForEach() receives an Action<T>. The action is called once for each element in the list.
list.ForEach(action);
A lambda expression is a common way to provide that action:
list.ForEach(item => {
// statements that use item
});
The action can also be a named method whose parameter type matches the list element type. A lambda is simply a concise choice when the action is local to the call.
Example 1 – C# List.ForEach() with an anonymous delegate
The List.ForEach() method accepts an Action<T> and invokes that action once for each element in the list.
The following program creates a list of three integers and passes an anonymous delegate to ForEach(). On each call, the current integer is received in the num parameter and printed.
The nums list contains int values, so the delegate parameter is also of type int. In general, the action passed to List<T>.ForEach() receives one value of type T at a time.
Program.cs
using System;
using System.Collections.Generic;
class Program {
static void Main(string[] args) {
//create list
List<int> nums = new List<int>();
//add elements to the list
nums.Add(56);
nums.Add(82);
nums.Add(94);
//list - foreach element
nums.ForEach(delegate(int num) {
Console.WriteLine(num);
});
}
}
Running the program invokes the delegate three times, once for each list element, and prints the values in list order.
Output
56
82
94
C# List.ForEach() with a lambda expression
The anonymous delegate in the previous example can be written more compactly with a lambda expression. The lambda parameter represents the current list element.
List<int> nums = new List<int> { 56, 82, 94 };
nums.ForEach(num => Console.WriteLine(num));
This produces the same three output lines. Use a block-bodied lambda when each element needs multiple statements.
nums.ForEach(num => {
int doubled = num * 2;
Console.WriteLine(doubled);
});
Example 2 – C# foreach statement with a List<int>
Here, the C# foreach statement iterates over the same kind of list without requiring a delegate. The iteration variable is named num, and during each pass it represents the current element.
Program.cs
using System;
using System.Collections.Generic;
class Program {
static void Main(string[] args) {
//create list
List<int> nums = new List<int>();
nums.Add(52);
nums.Add(68);
nums.Add(73);
//for each element in the list
foreach (int num in nums) {
Console.WriteLine(num);
}
}
}
Running the program prints each value in the order it appears in the list.
Output
52
68
73
C# foreach syntax for a List<T>
The foreach statement declares an iteration variable, reads each element from the collection in turn, and executes the loop body once for each element.
foreach (Type item in list) {
// statements that use item
}
When the element type is clear from the collection, var can also be used for the iteration variable.
foreach (var num in nums) {
Console.WriteLine(num);
}
Using break and continue in a C# List foreach loop
One practical advantage of the foreach statement is normal loop control. Use continue to skip the rest of the current iteration and break to stop the loop completely.
List<int> nums = new List<int> { 12, 25, 34, 48 };
foreach (int num in nums) {
if (num == 25) {
continue;
}
if (num > 40) {
break;
}
Console.WriteLine(num);
}
List.ForEach() calls a delegate for each element, so break and continue cannot be used inside that lambda as if it were a loop body. A return inside a void lambda returns from that single callback invocation; it does not stop List.ForEach() from processing later elements. If early exit is part of the logic, a foreach statement is usually clearer.
Example 3 – C# List.ForEach() with custom objects
List.ForEach() also works with lists of custom objects. In this example, each Car object is passed to the delegate, which reads its name and price fields.
Program.cs
using System;
using System.Collections.Generic;
class Program {
static void Main(string[] args) {
//create list
List<Car> cars = new List<Car>();
cars.Add(new Car("Toyota", 1250000));
cars.Add(new Car("Tata", 1300000));
cars.Add(new Car("Honda", 1150000));
//for each element in the list
cars.ForEach(delegate(Car car) {
Console.WriteLine(car.name + " - "+car.price);
});
}
}
class Car{
public string name;
public int price;
public Car(string name, int price){
this.name = name;
this.price = price;
}
}
Running the program prints the name and price of each Car in list order.
Output
Toyota - 1250000
Tata - 1300000
Honda - 1150000
C# foreach over a List of objects
The same List<Car> can be iterated with the foreach statement. This form is convenient when the body needs several statements or normal loop control.
foreach (Car car in cars) {
Console.WriteLine(car.name + " - " + car.price);
}
C# List foreach with an index
A plain foreach loop gives you the current element, not its numeric position. If the index is part of the task, a for loop is usually the most direct choice for a List<T>.
List<string> names = new List<string> { "Asha", "Ravi", "Meera" };
for (int i = 0; i < names.Count; i++) {
Console.WriteLine($"{i}: {names[i]}");
}
Output
0: Asha
1: Ravi
2: Meera
You can maintain a separate counter inside foreach, but when the position is required throughout the loop, for usually makes the intent easier to read.
C# List.ForEach() is not a LINQ operator
List<T>.ForEach() belongs to List<T>; it is not a LINQ extension method. LINQ operators such as Where(), Select(), and OrderBy() are primarily used to query or transform sequences. When the goal is simply to perform an action for every element in a List<T>, use a loop or List.ForEach() rather than building a LINQ query only for side effects.
C# foreach vs List.ForEach(): key differences
| Point | foreach statement | List.ForEach() |
|---|---|---|
| What it is | C# language statement | Method on List<T> |
| Works with | Many enumerable collection types | List<T> |
| Callback required | No | Yes, an Action<T> |
break and continue | Supported | Not available as loop-control statements inside the action |
| Index supplied automatically | No | No |
| Typical use | General collection iteration, especially when control flow is needed | Short actions applied to every item in an existing list |
Modifying a List while foreach or List.ForEach() is running
Avoid adding or removing elements from the same list while it is being iterated. Structural changes can invalidate the active iteration. For List<T>.ForEach(), modifying the underlying collection inside the action is not supported.
If items must be added or removed based on a condition, collect the required changes and apply them after the iteration, iterate over a copy when that matches the intended behavior, or use a suitable indexed loop that is written specifically for the modification pattern.
C# List foreach vs List.ForEach() performance
Both approaches visit the list elements linearly, so the overall work is proportional to the number of items. List<T>.ForEach() is documented as an O(n) operation. Small runtime differences can depend on the .NET version, JIT optimizations, delegate or lambda shape, and the work performed in each iteration.
For normal application code, choose the form that expresses the control flow clearly. If iteration performance is important in a measured hot path, benchmark the actual code and runtime instead of assuming that one form is always faster.
When to use C# foreach or List.ForEach()
Use foreach when you want conventional loop syntax, need break or continue, or may later work with a collection type other than List<T>. Use List.ForEach() when you already have a List<T> and want to apply a short Action<T> to every element.
In this C# Tutorial, we learned how the C# foreach statement and List.ForEach() method iterate through a list, and when each form is the clearer choice.
TutorialKart.com