Cách sử dụng Deligate trong C#
Delegate là cách C# liệt kê các phương thức chứa trong các lớp khác. Như bạn sẽ thấy, một delegate tương tự như một con trỏ hàm hay callback function trong C hay C++, nhưng chúng an toàn về kiểu và linh hoạt hơn. Delegate cũng làm việc tốt với ngôn ngữ C# và có thể nhắm tới cả các phương thức tĩnh ...
Delegate là cách C# liệt kê các phương thức chứa trong các lớp khác. Như bạn sẽ thấy, một delegate tương tự như một con trỏ hàm hay callback function trong C hay C++, nhưng chúng an toàn về kiểu và linh hoạt hơn. Delegate cũng làm việc tốt với ngôn ngữ C# và có thể nhắm tới cả các phương thức tĩnh và không tĩnh, đây là điều khó có thể làm được trong C++. Trong phần này, chúng ta sẽ xem cách các sự kiện mở rộng các delegate để mang lại một cách diễn đạt được định nghĩa tốt cho yêu cầu của client đối với việc sử lý sự kiện.
Sử dụng delegates Delegates được sử dụng để bao gói các hàm vào một đối tượng hàm có thể gọi và việc sử dụng giống như con trỏ hàm được sử dụng trong C và C++ hay trong các ngôn ngữ khác. Giống như các con trỏ hàm, các delegate cho phép bạn tách biệt một tham chiếu của hàm khỏi phần thực thi của nó, cho phép việc thực thi tồn tại trong một module riêng. Không giống như con trỏ hàm, delegate an toàn về kiểu cho nên trình biên dịch và .NET framework chắc chắn rằng mã lệnh được gọi qua delegate chạy một cách an toàn. Chúng ta có thể sử dụng delegate để đưa ra một phương thức quản lý luồng trong ứng dụng đa luồng. Một hàm xử lý luồng được tạo như một delegate và được gọi ở một luồng riêng biệt trong thời gian chạy. Delegate được sử dụng rộng rãi trong C# và đưa ra các xử lý sự kiện khi bạn phát triển các ứng dụng WindowsForm hay bạn đang sử dụng WebForm với ASP.NET. Nhiều delegate có thể được móc nối với nhau, nó làm cho việc xây dựng ứng dụng dễ dàng hơn bằng cách sử dụng các lớp delegates để xử lý sự kiện.
Tạo delegate Delegate trong C# được khai báo trong một quá trình gồm 2 bước. Đầu tiên một kiểu delegate sẽ được khai báo, và sau đó thể hiện của kiểu delegate sẽ được tạo. Một kiểu delegate được khai báo sử dụng từ khoá delegate cùng với method signature (phương thức mẫu - mẫu ở đây sử dụng như là định dạng để các thể hiện khác tuân theo) của delegate.
public delegate void OpDelegate(int First, int Second ) ;
Sử dụng delegate như là các phương thức callback Trường hợp thường dùng nhất của delegate là gọi ngược trở lại một phương thức để thực hiện một nhiện vụ được yêu cầu. Một delegate được sử dụng để thực hiện một callback thường được truyền như là một tham số cho contructor hay một phương thức khác và được gọi khi một callback được thực hiện.
public class BubbleSort { /// <summary> /// A delegate is used to define the sort order for two /// elements in the table. /// </summary> public delegate bool Order(object first, object second);
/// <summary> /// Sort elements in an Array object, using the Order /// delegate to determine how items should be sorted. /// </summary> /// <param name="table">Array to be sorted</param> /// <param name="sortHandler">Delegate to manage /// sort order.</param> public void Sort(Array table, Order sortHandler) { if(sortHandler == null) throw new ArgumentNullException();
bool nothingSwapped = false; int pass = 1; while(nothingSwapped == false) { nothingSwapped = true; for(int index = 0; index < table.Length - pass; ++index) { // Use an Order delegate to determine the sort order. if(sortHandler(table.GetValue(index), table.GetValue(index + 1)) == false) { nothingSwapped = false; object temp = table.GetValue(index); table.SetValue(table.GetValue(index + 1), index); table.SetValue(temp, index + 1); } } ++pass; } }
Lớp BubbleSort định nghĩa một kiểu delegate tên là Order, nó được sử dụng để quyết định quan hệ về thứ tự sắp xếp cho các phần tử trong một mảng. Phương thức được gắn với kiểu delegate Order chấp nhận 2 đối tượng như là tham số và so sánh chúng để quyết định quan hệ về thứ tự sắp xếp. Phương thức được mong đợi sẽ trả về true nếu phần tử đầu được sắp vào vị trí thấp hơn so với phần tử thứ 2 và trả về false trong các trường hợp còn lại. Phương thức BubbleSort.Sort nhận 2 tham số: mảng cần sắp và một thể hiện sẽ được gọi khi thực hiện việc sắp của delegate Order. Phương thức Sort sử dụng thuật toán sắp nổi bọt để lặp qua các phần tử trong mảng. Phần của thuật toán sắp nổi bọt cần so sánh 2 phần tử đứng gần nhau trong mảng để quyết định thứ tự đúng của chúng. Nếu không đúng thứ tự, chúng sẽ được đổi chỗ. Trong phương thức Sort, việc so sánh được thực hiện sử dụng delegate là tham số truyền vào. Cho phép một client của phương thức Sort có thể định nghĩa một thứ tự sắp xếp là delegate sao cho phương thức sort có thể sử dụng với bất kỳ loại đối tượng nào, bởi vì chỉ delegate cần hiểu các phần tử của mảng được sắp như thế nào. Chú ý: Nếu delegate được gọi thông qua một tham chiếu rỗng ( null ), một NullReferenceException sẽ được đưa ra tại thời điểm chạy (at runtime). Do đó, nên kiểm tra tham chiếu của delegate trước khi gọi nó. Trong phương thức BubbleSort.Sort, delegate Order đã được kiểm tra, nếu là rỗng một thông báo ArgumentNullException sẽ được đưa ra cho thành phần gọi. Ví dụ một ứng dụng sử dụng lớp BubbleSort để sắp các mảng integer
class DelegateSortApp { static int [] sortTable = {5,4,6,2,8,9,1,3,7,0}; static void Main(string[] args) { DelegateSortApp app = new DelegateSortApp();
// Print array in original order. foreach(int i in sortTable) Console.WriteLine(i);
Console.WriteLine("Sorting"); BubbleSort sorter = new BubbleSort(); BubbleSort.Order order = new BubbleSort.Order(SortOrder); sorter.Sort(sortTable, order);
foreach(int i in sortTable) Console.WriteLine(i); Console.WriteLine("Done"); }
// Delegate method; returns true if first is less than second static public bool SortOrder(object first, object second) { int firstInt = (int)first; int secondInt = (int)second; return firstInt < secondInt; } }