Bạn sử dụng các đại biểu trong C # là gì?
Bạn sử dụng các đại biểu trong C # là gì?
Câu trả lời:
Bây giờ chúng ta có các biểu thức lambda và các phương thức ẩn danh trong C #, tôi sử dụng các đại biểu nhiều hơn nữa. Trong C # 1, nơi bạn luôn phải có một phương pháp riêng để triển khai logic, việc sử dụng một ủy nhiệm thường không có ý nghĩa. Ngày nay, tôi sử dụng đại biểu cho:
Các đại biểu rất hữu ích cho nhiều mục đích.
Một trong những mục đích như vậy là sử dụng chúng để lọc chuỗi dữ liệu. Trong trường hợp này, bạn sẽ sử dụng một đại biểu vị từ chấp nhận một đối số và trả về true hoặc false tùy thuộc vào việc triển khai chính ủy nhiệm đó.
Đây là một ví dụ ngớ ngẩn - tôi chắc chắn rằng bạn có thể ngoại suy điều gì đó hữu ích hơn từ điều này:
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<String> names = new List<String>
{
"Nicole Hare",
"Michael Hare",
"Joe Hare",
"Sammy Hare",
"George Washington",
};
// Here I am passing "inMyFamily" to the "Where" extension method
// on my List<String>. The C# compiler automatically creates
// a delegate instance for me.
IEnumerable<String> myFamily = names.Where(inMyFamily);
foreach (String name in myFamily)
Console.WriteLine(name);
}
static Boolean inMyFamily(String name)
{
return name.EndsWith("Hare");
}
}
static Boolean inMyFamily(String name)
phương pháp là các đại biểu. Trong đó lấy một đại biểu làm tham số. Vì đại biểu chỉ là con trỏ hàm khi bạn chuyển tên phương thức vào phương thức .Where(delegate)
đó sẽ trở thành đại biểu. Vì inMyFamily trả về kiểu boolean nên nó thực sự được coi là một vị từ. Predicates chỉ là các đại biểu trả về các boolean.
Tìm thấy một câu trả lời thú vị khác:
Một đồng nghiệp vừa hỏi tôi câu hỏi này - điểm của các đại biểu trong .NET là gì? Câu trả lời của tôi rất ngắn gọn và một câu mà anh ấy chưa tìm thấy trên mạng: trì hoãn việc thực thi một phương pháp.
Nguồn: LosTechies
Giống như LINQ đang làm.
Bạn có thể sử dụng các đại diện để khai báo các biến và tham số kiểu hàm.
Thí dụ
Hãy xem xét mô hình "vay tài nguyên". Bạn muốn kiểm soát việc tạo và dọn dẹp tài nguyên, đồng thời cho phép mã máy khách "mượn" tài nguyên ở giữa.
Điều này khai báo một kiểu đại biểu.
public delegate void DataReaderUser( System.Data.IDataReader dataReader );
Bất kỳ phương thức nào khớp với chữ ký này đều có thể được sử dụng để khởi tạo một đại biểu kiểu này. Trong C # 2.0, điều này có thể được thực hiện ngầm, đơn giản bằng cách sử dụng tên của phương thức, cũng như bằng cách sử dụng các phương thức ẩn danh.
Phương thức này sử dụng kiểu làm tham số. Lưu ý lời kêu gọi của đại biểu.
public class DataProvider
{
protected string _connectionString;
public DataProvider( string psConnectionString )
{
_connectionString = psConnectionString;
}
public void UseReader( string psSELECT, DataReaderUser readerUser )
{
using ( SqlConnection connection = new SqlConnection( _connectionString ) )
try
{
SqlCommand command = new SqlCommand( psSELECT, connection );
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while ( reader.Read() )
readerUser( reader ); // the delegate is invoked
}
catch ( System.Exception ex )
{
// handle exception
throw ex;
}
}
}
Hàm có thể được gọi với một phương thức ẩn danh như sau. Lưu ý rằng phương thức ẩn danh có thể sử dụng các biến được khai báo bên ngoài chính nó. Điều này cực kỳ tiện dụng (mặc dù ví dụ có một chút giả thiết).
string sTableName = "test";
string sQuery = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + sTableName + "'";
DataProvider.UseReader( sQuery,
delegate( System.Data.IDataReader reader )
{
Console.WriteLine( sTableName + "." + reader[0] );
} );
Các đại biểu thường có thể được sử dụng thay cho một giao diện với một phương thức, một ví dụ phổ biến về điều này sẽ là mẫu quan sát. Trong các ngôn ngữ khác, nếu bạn muốn nhận được thông báo rằng điều gì đó đã xảy ra, bạn có thể xác định điều gì đó như:
class IObserver{ void Notify(...); }
Trong C #, điều này thường được thể hiện nhiều hơn bằng cách sử dụng các sự kiện, trong đó trình xử lý là một đại biểu, ví dụ:
myObject.SomeEvent += delegate{ Console.WriteLine("..."); };
Một nơi tuyệt vời khác để sử dụng đại biểu nếu khi bạn phải chuyển một vị từ vào một hàm, ví dụ: khi chọn một tập hợp các mục từ danh sách:
myList.Where(i => i > 10);
Trên đây là một ví dụ về cú pháp lambda, cũng có thể được viết như sau:
myList.Where(delegate(int i){ return i > 10; });
Một nơi khác có thể hữu ích để sử dụng các đại diện là đăng ký các chức năng của nhà máy, ví dụ:
myFactory.RegisterFactory(Widgets.Foo, () => new FooWidget());
var widget = myFactory.BuildWidget(Widgets.Foo);
Tôi hi vọng cái này giúp được!
Tôi đến đây thực sự muộn nhưng tôi gặp khó khăn trong việc tìm ra mục đích của các đại biểu ngày hôm nay và đã viết hai chương trình đơn giản đưa ra cùng một kết quả mà tôi nghĩ giải thích tốt mục đích của họ.
NoDelegates.cs
using System;
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Test.checkInt(1);
Test.checkMax(1);
Test.checkMin(1);
Test.checkInt(10);
Test.checkMax(10);
Test.checkMin(10);
Test.checkInt(20);
Test.checkMax(20);
Test.checkMin(20);
Test.checkInt(30);
Test.checkMax(30);
Test.checkMin(30);
Test.checkInt(254);
Test.checkMax(254);
Test.checkMin(254);
Test.checkInt(255);
Test.checkMax(255);
Test.checkMin(255);
Test.checkInt(256);
Test.checkMax(256);
Test.checkMin(256);
}
}
Delegates.cs
using System;
public delegate void Valid(int a);
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
v1(1);
v1(10);
v1(20);
v1(30);
v1(254);
v1(255);
v1(256);
}
}
Một cách sử dụng hơi khác là tăng tốc độ phản chiếu; tức là thay vì sử dụng phản chiếu mỗi lần, bạn có thể sử dụng Delegate.CreateDelegate
để tạo một đại biểu (đã nhập) cho một phương thức (a MethodInfo
) và gọi đại biểu đó thay thế. Sau đó, việc này sẽ nhanh hơn nhiều cho mỗi cuộc gọi, vì việc kiểm tra đã được thực hiện.
Với Expression
, bạn cũng có thể làm điều tương tự để tạo mã khi đang di chuyển - ví dụ: bạn có thể dễ dàng tạo một Expression
đại diện cho toán tử + cho một loại được chọn trong thời gian chạy (để cung cấp hỗ trợ toán tử cho các generic mà ngôn ngữ này không cung cấp) ; và bạn có thể biên dịch một Expression
đại biểu đã nhập - công việc đã hoàn thành.
Các đại biểu được sử dụng bất cứ khi nào bạn sử dụng các sự kiện - đó là cơ chế hoạt động của chúng.
Ngoài ra, các đại biểu rất hữu ích cho những việc như sử dụng các truy vấn LINQ. Ví dụ: nhiều truy vấn LINQ lấy một đại biểu (thường Func<T,TResult>
) có thể được sử dụng để lọc.
Một ví dụ có thể được thấy ở đây . Bạn có một phương pháp để xử lý một đối tượng đáp ứng các yêu cầu nhất định. Tuy nhiên, bạn muốn có thể xử lý đối tượng theo nhiều cách. Thay vì phải tạo các phương thức riêng biệt, bạn có thể chỉ cần gán một phương thức so khớp xử lý đối tượng cho một đại biểu và chuyển đại biểu cho phương thức chọn các đối tượng. Bằng cách đó, bạn có thể gán các phương thức khác nhau cho một phương thức bộ chọn. Tôi đã cố gắng làm cho điều này dễ hiểu.
Tôi sử dụng các đại biểu để giao tiếp với các chủ đề.
Ví dụ: tôi có thể có một ứng dụng win form tải xuống một tệp. Ứng dụng bắt đầu một chuỗi công nhân để thực hiện tải xuống (điều này ngăn GUI bị khóa). Luồng công nhân sử dụng các đại biểu để gửi thông báo trạng thái (ví dụ: tiến trình tải xuống) trở lại chương trình chính, để GUI có thể cập nhật thanh trạng thái.
Đối với trình xử lý sự kiện
Để truyền phương thức trong một tham số phương thức
Sự kiện, hoạt động bất kỳ khác
Bất cứ lúc nào bạn muốn đóng gói hành vi, nhưng gọi nó theo một cách thống nhất. Trình xử lý sự kiện, chức năng gọi lại, v.v. Bạn có thể thực hiện những việc tương tự bằng cách sử dụng Giao diện và phôi, nhưng đôi khi, hành vi không nhất thiết phải gắn với một kiểu hoặc đối tượng . Đôi khi bạn chỉ có hành vi mà bạn cần gói gọn.
Khởi tạo tham số lười biếng! Bên cạnh tất cả các câu trả lời trước đó (mẫu chiến lược, mẫu người quan sát, v.v.), các đại biểu cho phép bạn xử lý việc khởi tạo tham số lười biếng. Ví dụ: giả sử bạn có một hàm Download () mất khá nhiều thời gian và trả về một DownloadedObject nhất định. Đối tượng này được tiêu thụ bởi một Kho lưu trữ tùy thuộc vào một Điều kiện nhất định. Thông thường, bạn sẽ:
storage.Store(conditions, Download(item))
Tuy nhiên, với các ủy quyền (chính xác hơn là lambdas), bạn có thể làm như sau, bằng cách thay đổi chữ ký của cửa hàng để nó nhận được Điều kiện và Hàm <Item, DownloadedObject> và sử dụng nó như sau:
storage.Store(conditions, (item) => Download(item))
Do đó, bộ nhớ sẽ chỉ đánh giá ủy nhiệm nếu cần thiết, thực hiện tải xuống tùy thuộc vào Điều kiện.
Sử dụng đại biểu
Tham số so sánh trong In Array.Sort (T [] mảng, So sánh so sánh), List.Sort (So sánh so sánh), v.v.
Theo như tôi biết, các đại biểu có thể được chuyển đổi thành các con trỏ hàm. Điều này làm cho cuộc sống dễ dàng hơn RẤT NHIỀU khi tương tác với mã gốc sử dụng con trỏ hàm, vì chúng có thể được định hướng đối tượng một cách hiệu quả, mặc dù lập trình viên ban đầu không đưa ra bất kỳ điều khoản nào để điều đó xảy ra.
Delegate được sử dụng để gọi một phương thức bằng tham chiếu của nó. Ví dụ:
delegate void del_(int no1,int no2);
class Math
{
public static void add(int x,int y)
{
Console.WriteLine(x+y);
}
public static void sub(int x,int y)
{
Console.WriteLine(x-y);
}
}
class Program
{
static void Main(string[] args)
{
del_ d1 = new del_(Math.add);
d1(10, 20);
del_ d2 = new del_(Math.sub);
d2(20, 10);
Console.ReadKey();
}
}