Khi chúng ta thực hiện một chương trình giao diện đồ hoạ (Windows Form hay Windows Presentation Foundation ), chúng ta thường có những thao tác như nhấp chuột vào một nút hay nhập một đoạn văn bản. Những thao tác này buộc chương trình phải tạm dừng hoạt động để xử lý các nhiệm vụ của chúng ta. Khi các nhiệm vụ của chúng ta được đáp ứng, ví dụ hiển thị một thông điệp khi chúng ta nhấn nút, chương trình sẽ trở lại các hoạt động tại nơi nó tạm dừng. Để xử lý những tình huống khẩn cấp này, trình thực thi cần có hai thứ: một phương tiện để xác định những tình huống khẩn cấp đã xảy ra và một cách để xác định đoạn mã thực thi khi những tình huống khẩn cấp xảy ra.

Trong bài này chúng ta sẽ tìm hiểu:

  • Khái niệm và cách tạo delegate
  • Khai báo, xử lý và phát sinh sự kiện (event)

Delegate

Delegate trong C# tương tự như con trỏ đến các hàm trong C hay C++. Một delegate là một  biến kiểu tham chiếu chứa tham chiếu đến một phương thức. Tham chiếu có thể thay đổi tại thời điểm thực thi.

Delegate hữu ích khi thực thi sự kiện hay các phương thức call-back. Tất cả các delegate được thừa kế từ lớp System.Delegate.

Khai báo các delegates

Hình thức khai báo các delegates xác định các phương thức có thể được tham chiếu bởi delegate. Cú pháp khai báo một delegate:


delegate <return type> <delegate-name> <parameter list>

Phương thức được tham chiếu tới phải có cùng kiểu dữ liệu trả về (return type) và danh sách tham số (parameter list) với delegate. Ví dụ chúng ta có khai báo delegate như sau:


public delegate int MyDelegate (string s);

MyDelegate tham chiếu đến phương thức có kiểu dữ liệu trả về là int và có một tham số kiểu string.

Tạo thể hiện delegate

Một delegate sau khi được khai báo phải được tạo các thể hiện bằng từ khoá new cùng với một phương thức tương ứng. Ví dụ:


// khai báo delegate

public delegate void printString(string s);

// khai báo các phương thức

public void WriteToScreen(string s){

….

}

public void WriteToFile(string s){

….

}

// tạo các thể hiện của delegate

printString ps1 = new printString(WriteToScreen);

printString ps2 = new printString(WriteToFile);

Các phương thức được gọi thông qua các thể hiện, ví dụ:

// Gọi các phương thức từ các thể hiện delegate

ps1("Write something to screen.");

ps2("Write something to file.");

Mulicasting của một delegate

Các thể hiện (hay  đối tượng) delegate có thể kết hợp với nhau bằng toán tử +. Chỉ các delegate có cùng kiểu mới được kết hợp. Cũng có thể dùng toán tử – để xoá một thành phần delegate từ một delegate kết hợp.

Dùng cách thức kết hợp các thể hiện delegate có thể tạo ra một danh sách các phương thức sẽ được gọi khi một delegate được gọi. Đây chính là multicasting của một delegate.

Ví dụ tạo một delegate sau:


delegate int NumberChanger(int n);

Các phương thức mà delegate tham chiếu tới:

public int AddNum(int p) {

….

}

public int MultNum(int q) {

….

}

Tạo các thể hiện của delegate:


NumberChanger nc1 = new NumberChanger(AddNum);

NumberChanger nc2 = new NumberChanger(MultNum);

Kết hợp các thể hiện bằng toán tử +:


NumberChanger nc;

nc = nc1;

nc += nc2;

Gọi hai phương thức AddNum và MultNum trong cùng một thể hiện nc


nc(5);

Có thể xoá một thể hiện từ thể hiện kết hợp nc


nc -= nc2;

Sử dụng delegate

Sau đây là một minh hoạ đầy đủ về cách sử dụng delegate:


using System;

delegate int NumberChanger(int n);

namespace DelegateAppl {

class TestDelegate {

static int num = 10;

public static int AddNum(int p) {

num += p;

return num;

}

public static int MultNum(int q) {

num *= q;

return num;

}

public static int getNum() {

return num;

}

static void Main(string[] args) {

//create delegate instances

NumberChanger nc;

NumberChanger nc1 = new NumberChanger(AddNum);

NumberChanger nc2 = new NumberChanger(MultNum);

nc = nc1;

nc += nc2;

//calling multicast

nc(5);

Console.WriteLine("Value of Num: {0}", getNum());

nc -= nc2;

nc(5);

Console.WriteLine("Value of Num: {0}", getNum());

Console.ReadKey();

}

}

}

Kết quả:


Value of Num: 75

Value of Num: 80

Sự kiện (event)

Sự kiện là các hành động của người dùng như nhấn phím, nhấp chuột, di chuyển chuột, v.v. hay các sự xuất hiện như hệ thống phát sinh một thông báo. Hệ thống cần đáp ứng các sự kiện khi chúng xảy ra, ví dụ ngắt chương trình (interrupt).

Dùng delegate với sự kiện

Sự kiện được khai báo và phát sinh trong một lớp và kết hợp với trình xử lý sự kiện (event handler) dùng các delegates trong cùng lớp hay các lớp khác.

Lớp chứa sự kiện dùng để xuất bản sự kiện được gọi là lớp Publisher. Các lớp chấp nhận sự kiện này gọi là các lớp Subscriber.

Một đối tượng Publisher chứa định nghĩa của sự kiện và delegate. Sự kết hợp giữa delegate và sự kiện cũng được định nghĩa trong đối tượng này. Một đối tượng Publisher sẽ gọi sự kiện và thông báo đến các đối tượng khác.

Một đối tượng Subscriber chấp nhận sự kiện (từ đối tượng Publisher) và  cung cấp một trình xử lý sự kiện (event handler). Delegate trong lớp Publisher sẽ gọi phương thức (trình xử lý sự kiện) của lớp Subscriber.

Khai báo sự kiện

Để khai báo sự kiện trong một lớp, chúng ta thực hiện hai bước:

– Khai báo delegate cho sự kiện, ví dụ:


public delegate string MyDel(string str);

– Khai báo sự kiện dùng từ khoá event, ví dụ:


event MyDel MyEvent;

Cách khai báo và sử  dụng sự kiện sẽ được minh hoạ qua ví dụ hoàn chỉnh sau:


using System;

namespace ngocminhtran {

// khai báo delegate

public delegate string MyDel(string str);

class EventProgram {

// khai báo sự kiện

event MyDel MyEvent;

public EventProgram() {

// kết nối với trình xử lý  sự kiện (phương thức)

this.MyEvent += new MyDel(this.WelcomeUser);

}

public string WelcomeUser(string username) {

return "Welcome " + username;

}

static void Main(string[] args) {

EventProgram obj1 = new EventProgram();

// phát sinh sự kiện

string result = obj1.MyEvent("ngocminhtran.com");

Console.WriteLine(result);

}

}

}

Kết quả

 Welcome ngocminhtran.com 

Học C# và WPF >