GT C Sharp cơ bản – Bài 22 : Chương 21: Thẻ uỷ quyền

0
(0)

Chương 21: Thẻ uỷ quyền

 

Tác giả: Sưu tầm

 

Khái quát

Thẻ uỷ quyền tương tự như giao diện, mà bên trong nó chỉ rõ một hợp đồng giữa nơi gọi và trình thực thi. Thay vì xác định toàn bộ một giao diện, một thẻ uỷ quyền đơn thuần chỉ định một hình thức của một chức năng đơn lẻ. Đồng thời, giao diện được tạo ra tại thời điểm biên dịch, trong khi thẻ uỷ quyền được tạo tại thời gian chạy.

 

Sử dụng thẻ uỷ quyền

Sự chỉ định của thẻ uỷ quyền xác định hình thức của một chức năng, và để tạo một thể hiện của thẻ uỷ quyền, một người phải sử dụng một hàm so khớp với dạng thức đó. Đôi khi các thẻ uỷ quyền được tham chiếu đến như “những con trỏ hàm an toàn”. Tuy nhiên, không giống như con trỏ hàm, thẻ uỷ quyền trong C# có thể gọi nhiều hơn một hàm; nếu hai thẻ uỷ quyền được gộp lại với nhau, một thẻ uỷ quyền gọi đến cả hai thẻ uỷ quyền là kết quả.

 

Bởi vì bản chất linh động hơn của chúng, thẻ uỷ quyền là hữu ích khi người sử dụng muốn thay đổi hành vi. Ví dụ, nếu một lớp sưu tập cài đặt việc sắp xếp, nó có thể muốn hỗ trợ các thứ tự sắp xếp khác nhau. Việc sắp xếp có thể được điều khiển dựa trên một thẻ uỷ quyền mà nó định nghĩa một hàm so sánh.

using System;

 

public class Container {

     public delegate int CompareItemsCallback(object obj1, object obj2);

 

     public void Sort(CompareItemsCallback compare) {

          // not a real sort, just shows what the

          // inner loop code might do

          int x = 0;

          int y = 1;

          object item1 = arr[x];

          object item2 = arr[y];

          int order = compare(item1, item2);

     }

 

     object[] arr = new object[1]; // items in the collection

}

 

public class Employee {

     Employee(string name, int id) {

          this.name = name;

          this.id = id;

     }

 

     public static int CompareName(object obj1, object obj2) {

          Employee emp1 = (Employee) obj1;

          Employee emp2 = (Employee) obj2;

          return(String.Compare(emp1.name, emp2.name));

     }

 

     public static int CompareId(object obj1, object obj2) {

          Employee emp1 = (Employee) obj1;

          Employee emp2 = (Employee) obj2;

          if (emp1.id > emp2.id)

               return(1);

          if (emp1.id < emp2.id)

               return(-1);

          else

               return(0);

     }

 

     string name;

     int id;

}

 

class Test {

     public static void Main() {

          Container employees = new Container();

          // create and add some employees here

          // create delegate to sort on names, and do the sort

          Container.CompareItemsCallback sortByName =

          new Container.CompareItemsCallback(Employee.CompareName);

          employees.Sort(sortByName);

          // employees is now sorted by name

     }

}

Thẻ uỷ quyền định nghĩa trong lớp Container có hai tham số là hai đối tượng được so sánh, và trả ra một số nguyên chỉ rõ thứ tự của hai đối tượng. Hai hàm tĩnh được khai báo mà nó so khớp với thẻ uỷ quyền này (tất cả các thẻ uỷ quyền phải là các hàm tĩnh) như một phần của lớp Employee, với mỗi hàm mô tả một kiểu thứ tự khác nhau.

 

Khi container cần được sắp xếp, một thẻ uỷ quyền có thể được chuyển mà bên trong mô tả thứ tự nên được sử dụng, và hàm sắp xếp sẽ thực hiện việc sắp xếp.

 

Sao, phải chăng nó thật sự được cài đặt.

 

Thẻ uỷ quyền như các thành phần tĩnh

Một hạn chế của hướng tiếp cận này là người sử dụng muốn sử dụng cách sắp xếp phải tạo một thể hiện của thẻ uỷ quyền với hàm thích hợp. Tốt hơn nếu chúng không phải thực hiện như thế, và điều đó có thể được thực hiện bằng cách định nghĩa các thẻ uỷ quyền thích hợp như các thành phần tĩnh của Employee:

using System;

 

public class Container {

     public delegate int CompareItemsCallback(object obj1, object obj2);

    

     public void Sort(CompareItemsCallback compare) {

          // not a real sort, just shows what the

          // inner loop code might do

          int x = 0;

          int y = 1;

          object item1 = arr[x];

          object item2 = arr[y];

          int order = compare(item1, item2);

     }

 

     object[] arr = new object[1]; // items in the collection

}

 

class Employee {

     Employee(string name, int id) {

          this.name = name;

          this.id = id;

     }

 

     public static readonly Container.CompareItemsCallback SortByName =

                                               new Container.CompareItemsCallback(CompareName);

     public static readonly Container.CompareItemsCallback SortById =

                                               new Container.CompareItemsCallback(CompareId);

 

     public static int CompareName(object obj1, object obj2) {

          Employee emp1 = (Employee) obj1;

          Employee emp2 = (Employee) obj2;

          return(String.Compare(emp1.name, emp2.name));

     }

 

     public static int CompareId(object obj1, object obj2) {

          Employee emp1 = (Employee) obj1;

          Employee emp2 = (Employee) obj2;

          if (emp1.id > emp2.id)

               return(1);

          if (emp1.id < emp2.id)

               return(-1);

          else

               return(0);

     }

 

     string name;

     int id;

}

 

class Test {

     public static void Main() {

          Container employees = new Container();

          // create and add some employees here

          employees.Sort(Employee.SortByName);

          // employees is now sorted by name

     }

}

Điều này là dễ dàng hơn nhiều. Người sử dụng Employee không còn phải biết cách tạo thẻ uỷ quyền – họ có thể chỉ tham chiếu đến thành phần tĩnh.

 

Thẻ uỷ quyền như các thuộc tính tĩnh

Tuy nhiên, một điều không tốt là thẻ uỷ quyền luôn luôn được tạo, dù là nó không bao giờ được sử dụng. Điều này là hơi lãng phí. Sẽ là tốt hơn nếu thẻ uỷ quyền được tạo cẩn thận, khi cần. Điều này có thể được thực hiện bằng cách thay hàm tĩnh bằng các thuộc tính:

using System;

 

class Container {

     public delegate int CompareItemsCallback(object obj1, object obj2);

 

     public void SortItems(CompareItemsCallback compare) {

          // not a real sort, just shows what the

          // inner loop code might do

          int x = 0;

          int y = 1;

          object item1 = arr[x];

          object item2 = arr[y];

          int order = compare(item1, item2);

     }

 

     object[] arr; // items in the collection

}

 

class Employee {

     Employee(string name, int id) {

          this.name = name;

          this.id = id;

     }

 

     public static Container.CompareItemsCallback SortByName {

          get {

               return(new Container.CompareItemsCallback(CompareName));

          }

     }

 

     public static Container.CompareItemsCallback SortById {

          get {

               return(new Container.CompareItemsCallback(CompareId));

          }

     }

 

     static int CompareName(object obj1, object obj2) {

          Employee emp1 = (Employee) obj1;

          Employee emp2 = (Employee) obj2;

          return(String.Compare(emp1.name, emp2.name));

     }

 

     static int CompareId(object obj1, object obj2) {

          Employee emp1 = (Employee) obj1;

          Employee emp2 = (Employee) obj2;

          if (emp1.id > emp2.id)

               return(1);

          if (emp1.id < emp2.id)

               return(-1);

          else

               return(0);

     }

 

     string name;

     int id;

}

 

class Test {

     public static void Main() {

          Container employees = new Container();

          // create and add some employees here

          employees.SortItems(Employee.SortByName);

          // employees is now sorted by name

     }

}

Với phiên bản này, thay vì Employee.SortByName là một thẻ uỷ quyền, nó là một hàm trả ra một thẻ uỷ quyền có thể sắp xếp theo tên.

Ban đầu, ví dụ này có các thành phần thẻ uỷ quyền tĩnh riêng SortByName và SortById, và thuộc tính tạo thành phần tĩnh nếu trước đó nó chưa được cần đến. Điều này sẽ làm tốt nếu sự khởi tạo thẻ uỷ quyền là một cái gì đó đặt giá, và thẻ uỷ quyền dường như đựoc sử dụng lại.

Tuy nhiên, trong trường hợp này, quá đơn giản để tạo thẻ uỷ quyền cẩn thận và chỉ ra nó cho người sử dụng. Ngay khi hàm Sort trong Container được thực hiện với thẻ uỷ quyền, nó sẽ sẵn sàng cho sưu tập bởi trình gom rác.

Chú ý              Ví dụ này chỉ là để minh hoạ. Để cài đặt một lớp sưu tập mà nó thực hiện việc sắp xếp, các kỹ thuất sử dụng bởi Frameworks là dễ hơn nhiều. Hãy xem Chương 27, “Làm quen với .NET Frameworks”.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Related posts

GT C Sharp cơ bản – Bài 30 : Chương 29:  So sánh C# với các ngôn ngữ khác

GT C Sharp cơ bản – Bài 29 : Chương 28: Dòng lệnh

GT C Sharp cơ bản – Bài 28 : Chương 27: Tính tương hoạt