Delegates trong C# – Công cụ mạnh mẽ cho lập trình viên

Delegates trong C# – Công cụ mạnh mẽ cho lập trình viên

May 17, 2025 0 By Nam Vu

Bài viết trước mình đã đề cập đến Func, Action, Predicate đi liền với Expression bạn có thể đọc lại: https://blog.ntechdevelopers.com/func-vs-predicate-vs-expression-trong-c-net/

Ở bài viết này cũng với các từ khóa đó nhưng mình sẽ đi sâu vào bản chất delegate của chúng

Delegates là một tính năng quan trọng giúp nâng cao sức mạnh của C#. Chúng cho phép chúng ta truyền phương thức như một tham số, lưu trữ phương thức như một biến, và tạo ra các sự kiện hoặc callback tùy chỉnh.

  • Func: Đại diện cho phương thức nhận 0 hoặc nhiều tham số và trả về một giá trị bất kỳ.
  • Action: Đại diện cho phương thức nhận 0 hoặc nhiều tham số nhưng không trả về giá trị.
  • Predicate: Đại diện cho phương thức nhận một tham số duy nhất và trả về giá trị kiểu bool.

Trong thế giới phát triển .NET, Delegates, Func, Action và Predicate là những công cụ mạnh mẽ giúp viết mã linh hoạt và tái sử dụng cao. Mặc dù thoạt nhìn có vẻ giống nhau, nhưng mỗi loại lại có mục đích và cách sử dụng riêng biệt. Bài viết này sẽ giúp bạn hiểu rõ sự khác biệt giữa chúng và cách áp dụng hiệu quả trong thực tế.

1. Delegates: Nền tảng của Callback

Delegates là kiểu tham chiếu có thể lưu trữ tham chiếu đến các phương thức có cùng chữ ký. Điều này cho phép chúng ta truyền phương thức như một tham số, giúp việc gọi phương thức trở nên linh hoạt hơn.

Ví dụ:

// Khai báo delegate
delegate void MyDelegate(int number);

// Phương thức phù hợp với delegate
static void PrintNumber(int number)
{
    Console.WriteLine($"The number is {number}");
}

// Phương thức nhận delegate làm tham số
static void InvokeDelegate(MyDelegate del, int number)
{
    del(number);
}

// Sử dụng
InvokeDelegate(PrintNumber, 42);

Ở đoạn code trên, MyDelegate là một delegate nhận tham số int và không trả về giá trị. Chúng ta truyền phương thức PrintNumber vào InvokeDelegate, tạo ra hành vi callback.

2. Func: Delegate cho phương thức có giá trị trả về

Func<T> là một delegate generic giúp chúng ta đại diện cho một phương thức có thể nhận đến 16 tham số và trả về một giá trị.

Ví dụ:

// Phương thức tính bình phương
static int Square(int number)
{
    return number * number;
}

// Phương thức sử dụng Func
static int PerformOperation(Func<int, int> operation, int number)
{
    return operation(number);
}

// Sử dụng
int result = PerformOperation(Square, 5);
Console.WriteLine(result); // Output: 25

Ở đây, Func<int, int> đại diện cho một phương thức nhận một int và trả về int. Bằng cách truyền Square vào PerformOperation, chúng ta có thể dễ dàng thực hiện phép toán.

3. Action: Delegate cho phương thức không có giá trị trả về

Action<T> đại diện cho một phương thức không có giá trị trả về nhưng có thể nhận nhiều tham số.

Ví dụ:

// Phương thức in ra màn hình
static void PrintMessage(string message)
{
    Console.WriteLine(message);
}

// Phương thức sử dụng Action
static void PerformOperation(Action<string> operation, string message)
{
    operation(message);
}

// Sử dụng
PerformOperation(PrintMessage, "Hello, World!");

Ở đây, Action<string> đại diện cho một phương thức nhận string nhưng không trả về giá trị.

4. Predicate: Delegate kiểm tra điều kiện

Predicate<T> là một delegate đặc biệt nhận một tham số và trả về bool, thường dùng để lọc dữ liệu hoặc kiểm tra điều kiện.

Ví dụ:

// Phương thức kiểm tra số chẵn
static bool IsEven(int number)
{
    return number % 2 == 0;
}

// Phương thức sử dụng Predicate
static bool PerformOperation(Predicate<int> operation, int number)
{
    return operation(number);
}

// Sử dụng
bool isEven = PerformOperation(IsEven, 6);
Console.WriteLine(isEven); // Output: True

5. Truyền Delegates như một tham số

Việc truyền delegate giúp mã linh hoạt hơn, hỗ trợ mô hình lập trình hướng sự kiện và xử lý động.

Một số lưu ý quan trọng khi truyền delegate:

  • Kiểm tra null trước khi gọi delegate để tránh NullReferenceException.
  • Đảm bảo chữ ký phương thức phù hợp với delegate.
  • Thứ tự thực thi khi truyền nhiều delegate.

Ví dụ:

delegate void MyDelegate();

static void MethodA()
{
    Console.WriteLine("Method A");
}

static void MethodB()
{
    Console.WriteLine("Method B");
}

static void InvokeDelegates(params MyDelegate[] delegates)
{
    foreach (var del in delegates)
    {
        del?.Invoke();
    }
}

// Sử dụng
InvokeDelegates(MethodA, MethodB);

Kết quả:

Method A
Method B

Delegates, Func, Action và Predicate là những công cụ quan trọng trong lập trình .NET giúp viết mã linh hoạt và tái sử dụng cao. Hiểu và sử dụng tốt chúng sẽ giúp bạn làm chủ các mô hình lập trình callback, xử lý động và tối ưu hiệu suất hệ thống.

#ntechdevelopers