Bài viết này sẽ phần nào giúp các bạn hiểu rõ về Event và Delegate.
C# Hiếu Nguyễn 2014-08-15 16:19:47

Giới thiệu

Những lập trình viên khi mới bắt đầu làm việc với C# thường gặp rắc rối khi phân biệt hai thuật ngữ là event delegate. Và qua cách C# cho chúng ta khai báo event thường làm cho các bạn hiểu lầm về nó. Bài viết này sẽ phần nào giúp các bạn hiểu rõ về event delegate.

Tiền đề bài viết

Trong quá trình ban đầu làm việc với C#, tôi và các đồng nghiệp đã gặp rất nhiều khó khăn và thắc mắc với event delegate. Do đó, sau quá trình nghiên cứu và làm việc nhiều với C#, tôi tổng hợp mọi kiến thức của mình trong bài viết này nhằm giúp các lập trình viên giải quyết khó khăn khi tiếp xúc với event delegate.

Đối tượng hướng đến

Bài viết này dành cho những bạn lập trình viên đã từng làm việc nhiều với ngôn ngữ C#, có kinh nghiệm trong công việc lập trình và có kiến thức về lập trình hướng đối tượng.

Field và Property trong C#

Tôi có đoạn code sau

private int m_Bullet;//Field

public int Bullet//Property
{
    get { return m_Bullet; }
    set { m_Bullet = value; }
}

Như các bạn cũng đã thấy trong phần ghi chú, Field trong C# là một biến, còn Property nó giống một phương thức hơn. Trong ví dụ trên thì Property có 2 khối lệnh dùng để lấy hoặc gán giá trị cho Field m_Bullet và đây cũng là chức năng mà người ta thường sử dụng của Property. Ngoài ra, Property cũng có thể được khai báo như sau:

public int Bullet
{
    get;
    set;
}

Với kiểu khai báo này thì chúng ta có thể thấy có vẻ Property này không liên quan đến Field nào cả. Tuy nhiên với cách khai báo này thì trình biên dịch sẽ tự động tạo ra 1 Field vô danh mang thuộc tính private và chỉ có thể truy xuất thông qua Property trên.

Delegate là gì?

delegate là một kiểu dùng để mô tả phương thức, bao gồm có kiểu trả về và các tham số của phương thức. Và nó có khả năng gọi đến phương thức giống với cấu trúc hiện tại của nó. Ví dụ về delegate

class Test
{
    public delegate int DoSomethingWithNumbers(int param1, int param2);

    static int Sum(int x, int y)
    {
        return x + y;
    }

    static int Sub(int x, int y)
    {
        return x - y;
    }

    static int DoMath(int x, int y, DoSomethingWithNumbers z)
    {
        return z(x, y);
    }

    public static void Main()
    {
        Console.WriteLine(DoMath(2, 1, Sum).ToString());

        Console.WriteLine(DoMath(2, 1, Sub).ToString());
    }
}

Cần phải chú ý rằng, bản thân delegate chỉ là tham chiếu. Và được sử dụng để đại diện cho phương thức nào đó, chẳng hạn trong ví dụ trên thì delegate đại diện cho phương thức sum sub hoặc bất kỳ phương thức nào có 2 tham số là int và kiểu trả về là int.

Delegate và Event

Như đã nói ở trên, delegate suy cho cùng nó vẫn chỉ là Field, vậy Propety của nó như thế nào? Và đó chính là nguyên nhân mà event ra đời. Thông thường để khai báo một event, chúng ta làm như sau:

private delegate int DoSomethingWithNumbers(int param1, int param2);
public event DoSomethingWithNumbers NumberEvent;

Tôi đã tạo 1 delegate có tên là DoSomeThingWithNumbers và dùng nó để tạo một event có tên là NumberEvent. Nhìn vào đây thì nhiều người có thể lầm tưởng rằng NumberEvent là 1 Field nhưng thực chất, nó sẽ hoạt động như thế này:

private DoSomethingWithNumbers numberEvent;

public event DoSomethingWithNumbers NumberEvent
{
    add
    {
         this.numberEvent += value;
    }

    remove
    {
         this.numberEvent -= value;
    }
}

Như các bạn có thể thấy, event là một khối lệnh (gần giống với Property), khi chúng ta khai báo như trên, nó sẽ tự động sinh ra một Field delegate, nhiệm vụ của khối lệnh add là thêm một phương thức vào delegate numberEvent còn nhiệm vụ của khối lệnh remove là remove phương thức ra khỏi delegate. Như vậy, về bản chất thì delegate event hoàn toàn khác nhau.