Nếu bạn là một lập trình viên C, thì các ủy quyền có thể được coi là các con trỏ đến hàm. Tuy nhiên, các đại biểu trong C # không chỉ là một con trỏ hàm đơn giản. Bài viết này giải thích khái niệm đại biểu và cách sử dụng chúng trong lập trình hàng ngày.
Về cơ bản, các đại biểu cung cấp một mức định hướng. Chúng đóng gói một đoạn mã có thể được truyền xung quanh và thực thi theo cách an toàn về kiểu chữ. Thay vì thực hiện hành vi ngay lập tức, nó được chứa trong một đối tượng. Có nhiều hành động mà bạn có thể thực hiện trên đối tượng đó và một trong số chúng đang thực hiện hành vi được chứa đó.
Sử dụng các đại diện cho phép chúng ta viết các hàm bậc cao hơn, tức là các hàm có thể nhận các hàm dưới dạng tham số hoặc trả về các hàm dưới dạng giá trị trả về. Kiểu ủy nhiệm xác định chữ ký phương thức mà người ủy quyền có thể đại diện, cụ thể là kiểu trả về của phương thức và các kiểu tham số của nó. Trong ví dụ sau, Transformer là một đại diện có thể đại diện cho bất kỳ phương thức nào chấp nhận và trả về một số nguyên.
delegate int Transformer(int x);
Chúng ta có thể gán bất kỳ phương thức nào (bao gồm lambdas, instance hoặc phương thức tĩnh) cho một instance của Transformer đáp ứng chữ ký. Ví dụ -
Transformer square = x => x * x; Transformer cube = x => x * x * x; Console.WriteLine(square(3)); // prints 9 Console.WriteLine(cube(5)); // prints 125
Khi nào sử dụng đại biểu?
Ủy quyền thường được sử dụng khi mã muốn thực thi một số hành động không biết chi tiết về những hành động đó phải là gì nhưng biết giao diện của những hành động đó.
Trong lập trình, chúng ta thường phải đối mặt với các tình huống cần thực hiện một hành động cụ thể, nhưng chúng ta không biết trước phương thức nào chúng ta sẽ muốn gọi để thực hiện hành động đó. Các đại biểu giúp chúng tôi giải quyết vấn đề này bằng cách thay thế hành vi đó bằng một đại biểu và sau đó chuyển một trường hợp cụ thể của đại biểu đó với hành vi thích hợp khi cần theo ngữ cảnh và tình huống.
Để một người được ủy quyền có thể làm bất cứ điều gì, cần phải xảy ra bốn điều -
1) Loại ủy quyền cần được khai báo.
Về cơ bản, kiểu ủy quyền là định nghĩa của hàm mà nó đại diện, tức là nó bao gồm các kiểu tham số mà hàm sẽ chấp nhận và kiểu trả về mà nó trả về.
Ví dụ:kiểu ủy quyền đại diện cho một phương thức lấy hai số làm đầu vào và trả về một số có thể được khai báo là -
delegate int Processor(int numOne, int numTwo);
Bộ xử lý là một kiểu, tương tự như kiểu được tạo bởi một lớp. Để tạo một phiên bản kiểu này, bạn cần một phương thức lấy hai số làm đầu vào và trả về một bool.
2) Mã được thực thi phải được chứa trong một phương thức.
Xác định một phương thức có chữ ký chính xác như kiểu đại biểu ở trên và phương thức đó thực hiện những gì bạn muốn tùy theo tình huống trong thời gian chạy. Ví dụ:bất kỳ phương pháp nào sau đây có thể được sử dụng để tạo một phiên bản của Bộ xử lý, vì tất cả chúng đều nhận hai số và trả về một số.
static int Add(int numOne, int numTwo){ Return numOne + numTwo; } static int Subtract(int numOne, int numTwo){ Return numOne - numTwo; }
3) Một cá thể ủy quyền phải được tạo.
Bây giờ bạn đã có kiểu đại biểu và phương thức có chữ ký phù hợp, bạn có thể tạo một thể hiện của kiểu đại biểu đó. Khi làm điều này, về cơ bản chúng ta đang yêu cầu trình biên dịch C # thực thi phương thức này khi phiên bản ủy quyền được gọi.
Processor processorOne = new Processor(Add); Processor processorTwo = new Processor(Subtract);
Ví dụ trên giả định rằng các phương thức Thêm và Trừ được định nghĩa trong cùng một lớp mà chúng ta đang tạo thể hiện của đại biểu. Nếu các phương thức được định nghĩa trong một lớp khác, chúng ta sẽ cần phiên bản của lớp đó.
4) Phiên bản ủy quyền phải được gọi.
Đây chỉ là vấn đề gọi một phương thức trên cá thể ủy quyền, phương thức này được đặt tên, không có gì đáng ngạc nhiên, là Invoke. Phương thức này trên cá thể ủy quyền có cùng danh sách các tham số và kiểu trả về mà khai báo kiểu ủy quyền chỉ định. Gọi điện mời sẽ thực thi hành động của phiên bản ủy quyền.
int sum = processorOne.Invoke(3, 5);
Tuy nhiên, C # làm cho nó dễ dàng hơn. Bạn có thể gọi trực tiếp cá thể ủy quyền như thể bản thân nó là một phương thức. Ví dụ:
int difference = processorTwo(10, 6);
Kết hợp và Xóa đại biểu
Nếu chúng ta muốn thực thi một danh sách các hành động khác nhau với một lệnh gọi của một cá thể ủy quyền, C # cho phép chúng ta làm điều đó. Hệ thống. Loại ủy quyền có hai phương thức tĩnh, được gọi là Kết hợp và Loại bỏ.
1. Kết hợp
Tạo một đại biểu mới với một danh sách triệu gọi nối các danh sách triệu gọi của các đại biểu được truyền dưới dạng tham số. Khi thể hiện ủy quyền mới được gọi, tất cả các hành động của nó sẽ được thực thi theo thứ tự.
public static Delegate Combine(params Delegate[] delegates); // OR public static Delegate Combine(Delegate a, Delegate b);
Nếu bất kỳ hành động nào trong danh sách lệnh gọi ném ra một ngoại lệ, điều này sẽ ngăn không cho bất kỳ hành động nào tiếp theo được thực thi.
2. Xóa
Loại bỏ lần xuất hiện cuối cùng của danh sách lệnh gọi của một đại biểu khỏi danh sách triệu gọi của một đại biểu khác. Trả về một đại biểu mới với danh sách lệnh gọi được hình thành bằng cách lấy danh sách nguồn lệnh gọi và xóa lần xuất hiện cuối cùng của danh sách giá trị lệnh gọi.
public static Delegate Remove(Delegate source, Delegate value);
Tóm tắt
-
Các đại biểu đóng gói hành vi với một loại và tập hợp tham số cụ thể, tương tự như giao diện một phương thức.
-
Chữ ký kiểu được mô tả bởi khai báo kiểu người đại diện xác định phương thức nào có thể được sử dụng để tạo các trường hợp người được ủy quyền và chữ ký cho lệnh gọi.
-
Tạo một cá thể ủy quyền yêu cầu một phương thức mà chúng tôi muốn thực thi khi ủy quyền được gọi.
-
Các phiên bản đại diện là bất biến, tương tự như các chuỗi.
-
Mỗi phiên bản ủy quyền chứa một danh sách lệnh gọi - một danh sách các hành động.
-
Các phiên bản ủy quyền có thể được kết hợp và xóa khỏi nhau.
Ví dụ
using System; class Program{ delegate int Transformer(int x); delegate int Processor(int numOne, int numTwo); static void Main(){ Transformer square = x => x * x; Transformer cube = x => x * x * x; Console.WriteLine(square(3)); // prints 9 Console.WriteLine(cube(5)); // prints 125 Processor processorOne = new Processor(Add); Processor processorTwo = new Processor(Subtract); int sum = processorOne.Invoke(3, 5); Console.WriteLine(sum); // prints 8 int difference = processorTwo(10, 6); Console.WriteLine(difference); // prints 4 } static int Add(int numOne, int numTwo){ return numOne + numTwo; } static int Subtract(int numOne, int numTwo){ return numOne - numTwo; } }
Đầu ra
9 125 8 4