Giới thiệu delegate

Delegate (ủy quyền) là một kiểu dữ liệu nó dùng để tham chiếu đến các hàm có tham số và kiểu trả về nào đó phù hợp. Khi dùng đến delegate bạn có thể gán vào nó một, nhiều hàm (phương thức) có sự tương thích về tham số, kiểu trả về, sau đó dùng nó để gọi hàm (giống con trỏ trong C++), các event trong C# chính là các hàm được gọi thông qua delegate, bạn cũng có thể dùng delegate để xây dựng các hàm callback, đặc biệt là các Event

Sử dụng delegate cơ bản

1 Đầu tiên cần khai báo một delegate, khai báo giống như cách khai báo phương thức trong lớp với từ khóa delegate. Ví dụ sau khai báo một delegate có tên là ShowLog

public delegate void ShowLog(string message)

2 Khi đã có ShowLog, nó dùng như một kiểu dữ liệu để khai báo các biến, ví dụ:

ShowLog showLog;

3 Biến showLog ở trên có thể gán vào nó một phương thức nào đó có tham số và kiểu dữ liệu trả về tương đương, sau đó dùng delegate để thi hành phương thức, ví dụ có một lớp như sau:

public class Log
{
    public void info(string s)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine(string.Format("Info: {0}", s));
        Console.ResetColor();
    }

    public void warning(string s)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(string.Format("Waring: {0}", s));
        Console.ResetColor();
    }
}

Bạn thấy phương thức infowarning có tham số và kiểu trả về giống như định nghĩa của delegate ShowLog nên có thể gán hai phương thức này vào biến showLog, hãy xem đoạn mã sau:

Log log = new Log();
ShowLog showLog;

showLog = log.warning;      //Gán phương thức vào Delegate
showLog("TEST1");           //Thi hành Delegate


showLog = log.info;
showLog("TEST2");

Kết quả chạy đoạn code:

Waring: TEST1
Info: TEST2

Khi dùng delegate chạy một phương thức, cần đảm bảo biến delegate đó đã được gán phương thức (biến khác null), có thể bạn kiểm tra trước khi gọi ví dụ: if (showLog != null) showLog("Mgs") hoặc showLog?.Invoke("Mgs");

4 Một delegate có thể đưa vào nó nhiều phương thức để một lần gọi thi hành tất cả các phương thức nó chứa, một số lưu ý

  • Nối thêm một phương thức vào delegate dùng toán tử +=, ví dụ
    delegatevar += method1
  • Loại bỏ 1 phương ở cuối nếu phương thức đó có trong delegate (tính từ cuối) -=, ví dụ
    delegatevar -= method1

Ví dụ:

//...
showLog = null;
showLog += log.warning;
showLog += log.info;
showLog += log.warning;

//Một lần gọi thi hành tất cả các phương thức trong chuỗi delegate
showLog("TestLog");
Waring: TestLog
Info: TestLog
Waring: TestLog

5 Ngoài cách gán cho delegate một hàm có tên cụ thể như trên, bạn cũng có thể gán một phương thức Anonymou, ví dụ:

showLog += (x) => { Console.WriteLine(string.Format("===>{0}<===", x)); };

6 Các delegate cùng kiểu có thể kết hợp lại với nhau bằng toán tử +, ví dụ:
delegate_all = d1 + d2

Tải ví dụ: csharp-example-delegates