Anonymous Methods (C# 2.0) cho phép truyền khối mã (code block) làm tham số delegate không cần khai báo phương thức riêng tên. Chỉ có body, không có tên.
Cú pháp
delegate void NumberChanger(int n);
// Anonymous method gán cho delegate
NumberChanger nc = delegate(int x) {
Console.WriteLine("Anonymous Method: {0}", x);
};
Mã nguồn hoàn chỉnh
using System;
delegate void NumberChanger(int n);
namespace DelegateAppl {
class Demo {
static int num = 10;
// Named methods
public static void AddNum(int p) {
num += p;
Console.WriteLine("Named Method: {0}", num);
}
public static void MultNum(int q) {
num *= q;
Console.WriteLine("Named Method: {0}", num);
}
static void Main(string[] args) {
// Tạo delegate instance từ anonymous method
NumberChanger nc = delegate(int x) {
Console.WriteLine("Anonymous Method: {0}", x);
};
// Gọi qua delegate
nc(10); // Output: Anonymous Method: 10
// Gán named method
nc = new NumberChanger(AddNum);
nc(5); // Output: Named Method: 15
// Gán named method khác
nc = new NumberChanger(MultNum);
nc(2); // Output: Named Method: 30
Console.ReadKey();
}
}
}
Kết quả
Anonymous Method: 10
Named Method: 15
Named Method: 30
Anonymous Method vs Lambda Expression (C# 3.0+)
| Đặc điểm | Anonymous Method | Lambda Expression |
|---|---|---|
| Cú pháp | delegate(int x) { ... } | x => { ... } hoặc (x) => expr |
| Type inference | Không (phải khai báo type param) | Có (compiler infer) |
| Ref/out params | Hỗ trợ | Không hỗ trợ (trước C# 7.2) |
| Expression tree | Không thể | Có thể (Expression<Func<T>>) |
| Discard params | Không | Có (_ => ...) |
Lambda tương đương
NumberChanger nc = x => Console.WriteLine("Lambda: {0}", x);
nc(10);
Closure (Capture biến ngoài)
int factor = 2;
NumberChanger nc = delegate(int x) {
Console.WriteLine(x * factor); // Capture 'factor'
};
nc(5); // 10
factor = 3;
nc(5); // 15 - dùng giá trị MỚI của factor!
Lưu ý
- Anonymous method chủ yếu dùng trong code legacy (pre-C# 3.0) hoặc khi cần
ref/outparameter. - Code hiện đại: luôn ưu tiên Lambda — ngắn gọn, type inference, expression tree support.
- Capture variable (closure) có thể gây bug nếu biến thay đổi trong vòng lặp (classic
foreachclosure problem — đã fix từ C# 5).