Mục đích
Phương thức List<T>.ForEach(Action<T> action) thực thi delegate action cho **mỗi phần tử** trong list. Tương tự foreach nhưng dạng method, hữu ích cho functional style.
Ví dụ 1: Nhân mỗi số với 10
using System;
using System.Collections.Generic;
public class Demo
{
public static void MultiplyBy10(int n)
{
n *= 10; // Chỉ thay đổi bản cục bộ (value type)
Console.WriteLine(n);
}
public static void Main(string[] args)
{
List list = new List { 25, 50, 75, 100, 200, 250, 275, 300 };
Console.WriteLine("List gốc:");
foreach (int i in list) Console.WriteLine(i);
Console.WriteLine("\nList sau ForEach (nhân 10 - chỉ in ra):");
list.ForEach(MultiplyBy10); // 250, 500, 750...
}
}
Kết quả
List gốc:
25
50
75
100
200
250
275
300
List sau ForEach (nhân 10 - chỉ in ra):
250
500
750
1000
2000
2500
2750
3000
Ví dụ 2: Trừ 50 từ mỗi phần tử (Lambda)
using System;
using System.Collections.Generic;
public class Demo
{
public static void Main(string[] args)
{
List list = new List { 25, 50, 75, 100, 200, 250, 275, 300 };
Console.WriteLine("List gốc:");
foreach (int i in list) Console.WriteLine(i);
Console.WriteLine("\nForEach với lambda (trừ 50):");
list.ForEach(x => Console.WriteLine(x - 50));
// -25, 0, 25, 50, 150, 200, 225, 250
}
}
⚠️ Lưu ý quan trọng: ForEach KHÔNG sửa đổi List gốc
Với **value type** (int, struct), `action` nhận **bản sao** -> thay đổi bên trong không ảnh hưởng list.
List nums = new List { 1, 2, 3 };
nums.ForEach(x => x = x * 2); // Không thay đổi nums!
Console.WriteLine(string.Join(", ", nums)); // 1, 2, 3
Để sửa đổi list, dùng for loop hoặc List.ConvertAll (tạo list mới):
// Sửa đổi tại chỗ (in-place) - dùng for
for (int i = 0; i < nums.Count; i++) nums[i] *= 2;
// Hoặc tạo list mới
List doubled = nums.ConvertAll(x => x * 2);
Với Reference Type (class)
class Person { public string Name; }
var people = new List { new Person { Name = "A" }, new Person { Name = "B" } };
people.ForEach(p => p.Name = p.Name.ToLower()); // THAY ĐỔI object gốc!
// people[0].Name = "a"
So sánh ForEach vs foreach statement
| Đặc điểm | List.ForEach(Action) | foreach (var x in list) |
|---|---|---|
| Sửa đổi element (ref type) | Được (thay đổi object) | Được |
| Sửa đổi element (value type) | Không (bản sao) | Không (bản sao) |
| Break/Continue | Không hỗ trợ | Hỗ trợ |
| Return từ method bao | Không (trong lambda) | Hỗ trợ |
| Hiệu năng | Gọi delegate (chút overhead) | Tối ưu bởi compiler |
| LINQ | Không | Dễ chain (.Where().Select()) |
Khuyến nghị
- Ưu tiên
foreachstatement cho readability và control flow. - Dùng
ForEachcho side-effect đơn giản (logging, add to another collection). - Tránh logic phức tạp trong ForEach.