Trong các ứng dụng Windows Form, khi ta click một button hay click chọn một mục trong listbox, thì đều phát sinh một sự kiện (event). Chương trình có nhiệm vụ xử lý các sự kiện này. Chính cơ chế này đã tạo ra khả năng tương tác linh hoạt giữa người dùng và chương trình. Người dùng gửi đến chương trình các yêu cầu thông qua các sự kiện, chương trình đáp ứng sự kiện đó và thực hiện một tác vụ nào đó.
Những sự kiện đó đều được thực thi bởi cơ chế ủy quyền (delegate). Trong bài viết này, tôi sẽ giới thiệu với các bạn khái niệm delegate và cách sử dụng nó để tạo sự kiện trong C#.
Delegate là gì ?
Delegate đơn giản chỉ là một kiểu dữ liệu tham chiếu (reference type) dùng để đóng gói một phương thức với tham số và kiểu trả về xác định. Chúng ta có thể đóng gói bất kỳ phương thức nào trong một delegate thích hợp.
Delegate trong C# cũng tương tự như con trỏ hàm trong C++ (function pointer). Bạn sẽ hiểu rất nhanh về delegate nếu bạn đã từng sử dụng con trỏ hàm trong C++.
Delegate thường được sử dụng để tạo các sự kiện và các hàm callback cho chương trình.
Khai báo delegate
Để tạo delegate, bạn sử dụng từ khóa delegate theo cú pháp sau :
[access modifier] delegate [return type] <name> (<arguments>);
Trong đó :
- access modifier : là một trong các thuộc tính truy cập : private, public, protected, internal.
- return type : kiểu trả về của phương thức
- name : tên của delegate
- arguments : các tham số của phương thức
* Chú ý : delegate chỉ mô tả dạng tổng quát của phương thức, bao gồm
kiểu trả về và tham số. Còn phương thức cụ thể sẽ được truyền vào thông
qua một thể hiện (instance) của delegate. VD :
PHP Code:
public delegate void delSay(string Message);
Sử dụng delegate
Để sử dụng delegate, bạn phải tạo một thể hiện cho nó và truyền một phương thức phù hợp (về kiểu trả về và tham số) vào hàm khởi tạo của nó.
VD :
PHP Code:
namespace DelegateAndEventDemo
{
public delegate void delSay(string Msg);
class Program
{
static void Main(string[] args)
{
delSay speaker = new delSay(Speak);
speaker("Hello");
Console.ReadLine();
} private static void Speak(string Msg)
{
Console.WriteLine(Msg);
}
}
}
Như vậy, bằng cách trên, chúng ta đã "gắn" hàm Speak vào delegate delSay.
Kỹ thuật Multicast
C# cho phép chúng ta "gắn" nhiều phương thức vào cùng một delegate, miễn là các phương thức này có cùng kiểu trả về và tham số với delegate. Và khi ta gọi delegate này, tất cả các phương thức đã được "gắn" sẽ thi hành cùng lúc. Kỹ thuật này gọi là "Multicast".
Chú ý : một Multicast delegate chỉ chấp nhận phương thức có kiểu trả về là void.
PHP Code:
namespace DelegateAndEventDemo
{
public delegate void DoAction(string Msg);
class Program
{
static void Main(string[] args)
{
//Tạo 2 delegate riêng lẻ
DoAction speaker = new DoAction(Speak);
DoAction writer = new DoAction(Write);
//Thực hiện multi cast, ghép nhiều delegate lại với nhau
DoAction multicast = speaker + writer;
//Gọi delegate
multicast("Hello");
Console.ReadLine();
}
private static void Speak(string Msg)
{
Console.WriteLine("Speak : {0}",Msg);
}
private static void Write(string Msg)
{
Console.WriteLine("Write : {0}", Msg);
}
}
}
Như ví dụ trên : đầu tiên ta tạo 2 delegate speaker và writer gắn 2 hàm Speak và Write vào. Sau đó tạo delegate tên là multicast và "cộng" 2 delegate speaker, writer lại với nhau. Như vậy khi gọi delegate multicast, hai delegate speaker và writer sẽ đồng thời được gọi.
Ngoài toán tử "+", C# còn hỗ trợ toán tử "+=" và "-=" trên delegate. VD :
PHP Code:
multicast += speaker;
multicast -= writer;
Một trong những ứng dụng thường thấy nhất của delegate là sự kiện. Mỗi sự kiện thực chất là một delegate.
Bạn tạo một project mới kiểu Windows Form, vẽ lên Form một button tên là button1. Sau đó, bạn double click vào button, Visual Studio sẽ sinh cho bạn các đoạn mã sau :
Trong tập tin Form1.cs :
PHP Code:
...
private void button1_Click(object sender, EventArgs e)
{
}
...
PHP Code:
...
#region Windows Form Designer generated code
...
this.button1.Click += new System.EventHandler(this.button1_Click);
...
#endregion
...
Để cài đặt một sự kiện cho một lớp như trên. Bạn phải tạo một delegate và một event tương ứng. Cách khai báo như sau :
[access modifier] event [delegate type] <name>;
- access modifier : là thuộc tính truy cập (private, public, protected, internal)
- delegate type : kiểu delegate cần sử dụng
- name : tên của sự kiện
VD :
PHP Code:
public delegate void OnCreatingHandler();
public event OnCreatingHandler OnCreating;
Sau đó bạn có thể phát sự kiện ở bất cứ đâu trong lớp bằng cách gọi tên sự kiện và truyền vào tham số tương ứng.
Cuối cùng, bạn phải gắn sự kiện này với một hoặc nhiều phương thức để xử lý sự kiện.
VD đầy đủ :
PHP Code:
using System;
namespace EventDemo
{
class MyClass
{
public delegate void OnCreatingHandler(int Args); //khai báo delegate
public event OnCreatingHandler OnCreating; //khai báo sự kiện
public MyClass()
{
}
public void DoWork()
{
int Number = 10; //tham số cần truyền
OnCreating(Number); //phát sinh sự kiện
}
}
class Program
{
static void Main(string[] args)
{
MyClass M = new MyClass();
//gắn hàm xử lý vào sự kiện
M.OnCreating += new MyClass.OnCreatingHandler(M_OnCreating);
//sự kiện sẽ phát sinh khi gọi phương thức này
M.DoWork();
Console.ReadLine();
}
//hàm xử lý sự kiện
static void M_OnCreating(int Args)
{
Console.WriteLine("Tham so nhan duoc : {0}", Args);
}
}
}
Như vậy, chúng ta đã tìm hiểu xong về delegate và sự kiện trong C#. Ngoài những ứng dụng trên, bạn có thể tìm thấy một ứng dụng khác của delegate tại đây.

No comments:
Post a Comment