C# – Cơ bản Delegate (very basic)

Delegate là một kiến thức căn bản cần nắm vững khi bạn nhập môn C#, .NET. Mặc dù bạn có thể cho rằng delegate không cần thiết và tránh sử dụng nó (một cách trực tiếp) nhưng cuối cùng bạn vẫn phải nhận thấy rằng: mình không thể “sống” khi thiếu delegate. Delegate không khó hiểu cũng như không khó để áp dụng, nếu bạn dành một chút thời gian nghiên cứu.

Delegate là gì?

Trong tiếng Việt, delegate được dịch là “ủy nhiệm hàm”, tuy nhiên mọi người đều không sử dụng từ này mà gọi bằng tên gốc là delegate. Thật tốt nếu bạn đã từng biết qua trong C/C++, đặc biệt về khái niệm con trỏ, bởi vì delegate tương tự như con trỏ hàm trong C++.

Một delegate giống như một “người đại diện” hay “đại sứ”. Một delegate có thể được dùng để tạo một bao đóng (encapsulation) cho bất kì phương thức nào, miễn là nó phù hợp (kiểu trả về, tham số). Là một “đại sứ”, delegate có thể triệu gọi phương thức bất kì nơi nào: từ đối tượng này đến đối tượng kia, từ thread này sang thread kia,… Đây là đặc điểm chính của delegate, bạn sẽ cần nhớ lại điều này khi giải quyết các vấn đề thường gặp như truyền dữ liệu giữa hai Form, xử lý lỗi “Cross-thread operation not valid”, tạo event, …

Ngoài ra, bởi vì là một đối tượng, delegate có thể được truyền vào làm tham số của các phương thức. Bạn có thể hiểu đơn giản: delegate là một đối tượng dùng để bao đóng một hoặc nhiều phương thức (Multicast), hay có thể coi delegate là một sự kết hợp giữa đối tượng và phương thức.

Ta sẽ học cách sử dụng delegate qua 3 bước:

  •  Khai báo
  •  Khởi tạo
  • Thực thi

Khai báo

Là một đại diện của phương thức và là một kiểu dữ liệu, cách khai báo delegate giống như một sự kết hợp giữa khai báo đối tượng và phương thức. Một delegate được khai báo theo cú pháp sau:

[modifier] delegate return-type Identifier ([formal-parameters])

Trong đó:

  • modifier: phạm vi truy xuất (public, private, protected, internal)
  • delegate: từ khóa
  • return-type: kiểu dữ liệu trả về
  • Identifier: định danh của delegate
  • formal-parameters: danh sách các tham số hình thức

Các phần trong cặp ngoặc vuông [] là tùy chọn.

Ví dụ:

public delegate int DoSomething(int x, int y)

Khai báo một delegate có tên DoSomething, bạn có thể dùng delegate này đại diện cho bất kì phương thức nào yêu cầu hai tham số kiểu int và trả về kiểu int.

Khởi tạo

Giả sử  ta có một phương thức sau, có kiểu trả về và tham số tương ứng với delegate DoSomething trên:

int Add(int x,int y)
{
return x+y;
}

Khởi tạo delegate từ một phương thức có sẵn, bạn cần truyền phương thức mà delegate sẽ đại diện vào trong constructor. Bạn có thể khởi tạo delegate theo một trong hai cách sau. Chúng tương đương nhau khi được biên dịch:

// cách 1
DoSomething myDelegate = new DoSomething(Add)

// cách 2
DoSomething myDelegate = Add;

Hoặc sử dụng tên đầy đủ của phương thức:

DoSomething obj = MyNamespace1.Program.Add;

Thay vì tạo phương thức Add() trên, bạn có thể sử dụng anonymous method hoặc lambda expression để tạo đối tượng:

// anonymous method
DoSomething obj = delegate(int x,int y){
return x+y;
};

// lambda expression
DoSomething obj = (x,y) => x+y;

Thực thi

Có hai cách để bạn thực thi delegate.

Coi delegate như một phương thức:

myDelegate(a, b)

và như một đối tượng, bằng cách gọi phương thức Invoke():

myDelegate.Invoke(a, b)

Ví dụ

class Program
{
    public delegate int DoSomething(int x,int y);

    public static void Main(string[] args)
    {
        Math m=new Math();
        DoSomething obj = (x,y)=>x+y;

        int value=obj(3,4);

        Console.WriteLine(value); // output: 7
        Console.ReadKey();
    }
}

Tiếp theo là gì?

Sau khi hiểu được cơ bản delegate, bạn có thể cần tìm hiểu thêm về event. Trong .NET cũng có những delegate được tạo sẵn (build-in), bạn có thể tìm thấy các vấn đề này trong blog của tôi tại:

–          Anonymous Method

–          Lamdba Expression

–          Event

Một series hướng dẫn khá đầy đủ về delegate và event trên codeproject, bao gồm cả multicast delegate:

https://yinyangit.wordpress.com

Advertisements

8 thoughts on “C# – Cơ bản Delegate (very basic)

  1. Theo mình hiểu thì delegate là 1 dạng kiểu để bao bọc 1 hoặc nhiều method để có thể tiện sử dụng trong 1 project, vậy việc sử dụng delegate là hoàn toàn ko bắt buộc vì mình vẫn có thể dùng nhiều cách để “đi vòng” mà. Nếu mình có gì sai thì xin chỉ giáo .

    Trả lời
  2. Đúng vậy, tùy theo kiểu delegate mình tạo ra mà compiler sẽ sinh ra một lớp tương ứng kế thừa từ Delegate hay MulticastDelegate. delegate chỉ là một tính năng mới trong .Net và vẫn có thể thay thế được bởi những cách thông thường như các ngôn ngữ lập trình trước đây.

    Vì đây chỉ là bài viết giới thiệu rất cơ bản nên mình không đi sâu hơn, ngoài ra các hướng dẫn về delegate cũng khá nhiều.

    Cảm ơn bạn đã góp ý!

    Trả lời
  3. Yin Yang có thể cho mình hỏi về vấn đề này được không:
    Mình sử dụng hàm Invoke(delegate) để thực thi một công việc, đại loại như sau:

    void A()
    {
    Invoke(B);
    }

    Mình muốn hàm A đợi cho B thực hiện xong thì A sẽ kiểm tra một số giá trị do B trả về, tuy nhiên, khi chạy thì sau khi qua câu lệnh Invoke thì hàm A tự động kết thúc. Vì Invoke ko tạo thread mới nên mình ko dùng phương thức Thread.Join() để A chờ B được. Tạm thời mình khắc phục bằng cách để một vòng lặp do while() để làm cho A chờ cho B thực thi xong. Nhưng theo mình thấy thì cách này không tối ưu lắm (nhiều khi chtrình hơi đơ). Ko biết có giải pháp nào khác không.

    Mong Yin Yang giúp đỡ. Cảm ơn.

    Trả lời
  4. Hiện tại thì mình cũng làm như thế này.

    B là một hàm của lớp C nên trong lớp C mình thêm một biến Done để thông báo xem là B có thực thi xong chưa, khi nào B thực thi xong thì trước khi thoát hàm B, mình gán Done = true; và mình sửa lại như sau:

    void A()
    {
    C test = new C();
    Invoke(test.B);

    do
    {
    if(test.Done == true)
    {
    break;
    }
    }while(TRUE);

    }

    Tạm thời giải pháp của mình là vậy :D, mong nhận được góp ý từ bạn!

    Trả lời

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s