• HÃY CÙNG TẠO & THẢO LUẬN CÁC CHỦ ĐỀ KIẾN THỨC [Vn Kiến Thức] - Định hướng VnKienthuc.com
    -
    Mọi kiến thức & Thông tin trên VnKienthuc chỉ mang tính chất tham khảo, Diễn đàn không chịu bất kỳ trách nhiệm liên quan
    - VnKienthuc tạm khóa đăng ký tài khoản tự động để hạn chế SEO bẩn, SPAM, quảng cáo. Chưa đăng ký, KHÁCH vẫn có thể đọc và bình luận.

uocmo_kchodoi

Moderator
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. Delegate tương tự như con trỏ hàm trong C++. Nó được sử dụng để triển khai các sự kiện và các phương thức call-back. Tất cả delegate được kế thừa một cách ngầm định từ lớp System.Delegate 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.

1. Khai báo Delegate trong C#

Khai báo Delegate trong C# quyết định các phương thức mà có thể được tham chiếu bởi Delegate đó. Một Delegate có thể tham chiếu tới một phương thức, mà có cùng dấu hiệu như của Delegate đó.

Ví dụ, xét một delegate sau đây:

public delegate int MyDelegate (string s);

Delegate trên có thể được sử dụng để tham chiếu bất kỳ phương thức mà có một tham sốstring đơn và trả về một biến kiểu int.

Cú pháp để khai báo delegate trong C# là:

delegate <kiểu_trả_về> <tên_delegate> <danh_sách_tham_số>

2. Khởi tạo Delegate trong C#

Khi một kiểu delegate được khai báo, một đối tượng delegate phải được tạo với từ khóa new và được liên kết với một phương thức cụ thể. Khi tạo một delegate, tham số được truyền tới biểu thức new được viết tương tự như một lời gọi phương thức, nhưng không có tham số tới phương thức đó. Ví dụ:

public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);


Ví dụ sau minh họa cách khai báo, khởi tạo và sử dụng một delegate mà có thể được sử dụng để tham chiếu các phương thức mà nhận một tham số integer và trả về một giá trị integer.

using System;
delegate int NumberChanger(int n);
namespace VietJackCsharp
{
class TestCsharp
{
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)
{
Console.WriteLine("Vi du minh hoa Delegate trong C#");
Console.WriteLine("----------------------------------");

//tao cac doi tuong delegate
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);

//goi cac phuong thuc boi su dung cac doi tuong delegate
nc1(25);
Console.WriteLine("Gia tri cua num la: {0}", getNum());
nc2(5);
Console.WriteLine("Gia tri cua num la: {0}", getNum());
Console.ReadKey();
}
}
}
Nếu bạn không sử dụng lệnh Console.ReadKey(); thì chương trình sẽ chạy và kết thúc luôn (nhanh quá đến nỗi bạn không kịp nhìn kết quả). Lệnh này cho phép chúng ta nhìn kết quả một cách rõ ràng hơn.

Biên dịch và chạy chương trình C# trên sẽ cho kết quả sau:


delegate.PNG

3. Multicast một Delegate trong C#

Các đối tượng Delegate có thể được hợp thành bởi sử dụng toán tử "+". Một delegate được hợp thành gọi hai Delegate mà nó được hợp thành từ đó. Chỉ có các delegate cùng kiểu có thể được hợp thành. Toán tử "-" có thể được sử dụng để gỡ bỏ một delegate thành phần từ một delegate được hợp thành.

Sử dụng thuộc tính này của các delegate, bạn có thể tạo một danh sách triệu hồi của các phương thức mà sẽ được gọi khi delegate đó được triệu hồi. Điều này được gọi làMulticasting của một Delegate. Chương trình ví dụ sau minh họa Multicasting của một Delegate trong C#:

using System;
delegate int NumberChanger(int n);
namespace VietJackCsharp
{
class TestCsharp
{
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)
{
Console.WriteLine("Vi du minh hoa Delegate trong C#");
Console.WriteLine("----------------------------------");

//tao cac doi tuong delegate
NumberChanger nc;
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
nc = nc1;
nc += nc2;

//goi multicast
nc(5);
Console.WriteLine("Gia tri cua num la: {0}", getNum());
Console.ReadKey();
}
}
}
Biên dịch và chạy chương trình C# trên sẽ cho kết quả sau:


delegate-1.PNG

4. Cách sử dụng Delegate trong C#

Ví dụ sau minh họa cách sử dụng của delegate trong C#. Delegate với tên printString có thể được sử dụng để tham chiếu phương thức mà nhận một chuỗi như là input và không trả về cái gì.

Chúng ta sử dụng delegate này để gọi hai phương thức: phương thức đầu tiên in chuỗi tới Console, và phương thức thứ hai in nó tới một File.

using System;
using System.IO;
namespace VietJackCsharp
{
class TestCsharp
{
static FileStream fs;
static StreamWriter sw;

// khai bao delegate
public delegate void printString(string s);

// phuong thuc de in tren console
public static void WriteToScreen(string str)
{
Console.WriteLine("Chuoi la: {0}", str);
}

//phuong thuc nay de ghi du lieu vao file
public static void WriteToFile(string s)
{
fs = new FileStream("c:\\message.txt",
FileMode.Append, FileAccess.Write);
sw = new StreamWriter(fs);
sw.WriteLine(s);
sw.Flush();
sw.Close();
fs.Close();
}

// phuong thuc nay nhan delegate lam tham so va su dung no de
// goi cac phuong thuc neu can
public static void sendString(printString ps)
{
ps("Hoc C# co ban va nang cao tai VietJack");
}
static void Main(string[] args)
{
Console.WriteLine("Vi du minh hoa Delegate trong C#");
Console.WriteLine("----------------------------------");

printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
sendString(ps1);
sendString(ps2);
Console.ReadKey();
}
}
}
Biên dịch và chạy chương trình C# trên sẽ cho kết quả sau:


delegate-2.PNG

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. Chúc các bạn thành công!

Nguồn: vietjack.com
 
Sửa lần cuối bởi điều hành viên:
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, … 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)
 

Chủ đề mới

VnKienthuc lúc này

Không có thành viên trực tuyến.

Định hướng

Diễn đàn VnKienthuc.com là nơi thảo luận và chia sẻ về mọi kiến thức hữu ích trong học tập và cuộc sống, khởi nghiệp, kinh doanh,...
Top