Apa penggunaan delegasi Anda di C #?
Apa penggunaan delegasi Anda di C #?
Jawaban:
Sekarang kita memiliki ekspresi lambda dan metode anonim di C #, saya menggunakan delegasi lebih banyak lagi. Dalam C # 1, di mana Anda selalu harus memiliki metode terpisah untuk mengimplementasikan logika, menggunakan delegasi seringkali tidak masuk akal. Hari-hari ini saya menggunakan delegasi untuk:
Delegasi sangat berguna untuk banyak tujuan.
Salah satu tujuan tersebut adalah menggunakannya untuk memfilter urutan data. Dalam hal ini, Anda akan menggunakan delegasi predikat yang menerima satu argumen dan mengembalikan true atau false tergantung pada implementasi delegasi itu sendiri.
Berikut adalah contoh konyol - saya yakin Anda dapat memperkirakan sesuatu yang lebih berguna dari ini:
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)
metode adalah delegasi. Di mana mengambil delegasi sebagai parameter. Karena delegasi hanyalah penunjuk fungsi saat Anda meneruskan nama metode ke .Where(delegate)
yang menjadi delegasi. Karena inMyFamily mengembalikan tipe boolean, ini sebenarnya dianggap sebagai predikat. Predikat hanyalah delegasi yang mengembalikan boolean.
Menemukan jawaban menarik lainnya:
Seorang rekan kerja baru saja menanyakan pertanyaan ini kepada saya - apa gunanya delegasi di .NET? Jawaban saya sangat singkat dan yang tidak dia temukan secara online: untuk menunda pelaksanaan suatu metode.
Sumber: LosTechies
Seperti yang dilakukan LINQ.
Anda dapat menggunakan delegasi untuk mendeklarasikan variabel dan parameter dengan tipe fungsi.
Contoh
Pertimbangkan pola "pinjaman sumber daya". Anda ingin mengontrol pembuatan dan pembersihan sumber daya, sambil mengizinkan kode klien untuk "meminjam" sumber daya di antaranya.
Ini mendeklarasikan tipe delegasi.
public delegate void DataReaderUser( System.Data.IDataReader dataReader );
Metode apa pun yang cocok dengan tanda tangan ini dapat digunakan untuk membuat instance delegasi jenis ini. Di C # 2.0, ini bisa dilakukan secara implisit, cukup dengan menggunakan nama metode, serta dengan menggunakan metode anonim.
Metode ini menggunakan tipe sebagai parameter. Catat permintaan delegasi.
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;
}
}
}
Fungsi tersebut dapat dipanggil dengan metode anonim sebagai berikut. Perhatikan bahwa metode anonim dapat menggunakan variabel yang dideklarasikan di luar dirinya sendiri. Ini sangat berguna (meskipun contohnya sedikit dibuat-buat).
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] );
} );
Delegasi sering kali dapat digunakan sebagai pengganti antarmuka dengan satu metode, contoh umum dari ini adalah pola pengamat. Dalam bahasa lain jika Anda ingin menerima pemberitahuan bahwa sesuatu telah terjadi, Anda mungkin mendefinisikan sesuatu seperti:
class IObserver{ void Notify(...); }
Dalam C # ini lebih sering diekspresikan menggunakan peristiwa, di mana penangannya adalah seorang delegasi, misalnya:
myObject.SomeEvent += delegate{ Console.WriteLine("..."); };
Tempat lain yang bagus untuk menggunakan delegasi jika ketika Anda harus meneruskan predikat ke dalam suatu fungsi, misalnya saat memilih sekumpulan item dari daftar:
myList.Where(i => i > 10);
Di atas adalah contoh sintaks lambda, yang juga bisa ditulis sebagai berikut:
myList.Where(delegate(int i){ return i > 10; });
Tempat lain yang berguna untuk menggunakan delegasi adalah mendaftarkan fungsi pabrik, misalnya:
myFactory.RegisterFactory(Widgets.Foo, () => new FooWidget());
var widget = myFactory.BuildWidget(Widgets.Foo);
Saya harap ini membantu!
Saya datang terlambat tetapi saya mengalami kesulitan untuk mengetahui tujuan delegasi hari ini dan menulis dua program sederhana yang memberikan hasil yang sama yang menurut saya menjelaskan tujuan mereka dengan baik.
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);
}
}
Penggunaan yang sedikit berbeda adalah untuk mempercepat refleksi; yaitu daripada menggunakan refleksi setiap kali, Anda dapat menggunakan Delegate.CreateDelegate
untuk membuat delegasi (diketik) ke metode (a MethodInfo
), dan memanggil delegasi itu sebagai gantinya. Ini kemudian jauh lebih cepat untuk setiap panggilan, karena pemeriksaan telah dilakukan.
Dengan Expression
, Anda juga dapat melakukan hal yang sama untuk membuat kode dengan cepat - misalnya, Anda dapat dengan mudah membuat Expression
yang mewakili operator + untuk jenis yang dipilih saat runtime (untuk memberikan dukungan operator untuk obat generik, yang tidak disediakan oleh bahasa) ; dan Anda dapat mengkompilasi Expression
ke delegasi yang diketik - pekerjaan selesai.
Delegasi digunakan setiap kali Anda menggunakan acara - itulah mekanisme kerjanya.
Selain itu, delegasi sangat berguna untuk hal-hal seperti menggunakan kueri LINQ. Misalnya, banyak kueri LINQ mengambil delegasi (sering kali Func<T,TResult>
) yang dapat digunakan untuk pemfilteran.
Contohnya seperti yang terlihat di sini . Anda memiliki metode untuk memproses objek yang memenuhi persyaratan tertentu. Namun, Anda ingin dapat memproses objek dengan berbagai cara. Alih-alih harus membuat metode terpisah, Anda cukup menetapkan metode pencocokan yang memproses objek ke delegasi dan meneruskan delegasi ke metode yang memilih objek. Dengan begitu, Anda dapat menetapkan metode yang berbeda ke metode satu pemilih. Saya mencoba membuat ini mudah dimengerti.
Saya menggunakan delegasi untuk berkomunikasi dengan utas.
Misalnya, saya mungkin memiliki aplikasi formulir menang yang mengunduh file. Aplikasi memulai utas pekerja untuk melakukan unduhan (yang mencegah GUI mengunci). Utas pekerja menggunakan delegasi untuk mengirim pesan status (misalnya kemajuan unduhan) kembali ke program utama, sehingga GUI dapat memperbarui bilah status.
Untuk penanganan acara
Untuk melewatkan metode dalam parameter metode
Acara, operasi anynch lainnya
Kapan pun Anda ingin merangkum perilaku, tetapi panggil dengan cara yang seragam. Penangan Peristiwa, fungsi panggilan-kembali, dll. Anda dapat mencapai hal-hal serupa menggunakan Antarmuka dan cast, tetapi terkadang, perilaku tidak selalu terkait dengan jenis atau objek . Terkadang Anda hanya memiliki perilaku yang perlu Anda rangkum.
Inisialisasi parameter malas! Selain semua jawaban sebelumnya (pola strategi, pola pengamat, dll), delegasi memungkinkan Anda menangani inisialisasi parameter yang lambat. Misalnya, Anda memiliki fungsi Download () yang membutuhkan cukup banyak waktu dan mengembalikan DownloadedObject tertentu. Objek ini dikonsumsi oleh Penyimpanan bergantung pada Kondisi tertentu. Biasanya, Anda akan:
storage.Store(conditions, Download(item))
Namun, dengan delegasi (lebih tepatnya, lambda) Anda bisa melakukan hal berikut, dengan mengubah tanda tangan penyimpanan sehingga menerima Kondisi dan Fungsi <Item, DownloadedObject> dan menggunakannya seperti ini:
storage.Store(conditions, (item) => Download(item))
Oleh karena itu, penyimpanan hanya akan mengevaluasi delegasi jika perlu, menjalankan unduhan bergantung pada Ketentuan.
Penggunaan delegasi
Parameter perbandingan dalam In Array.Sort (T [] array, Comparisonarison), List.Sort (Perbandingan perbandingan), dll.
Sejauh yang saya tahu, delegasi dapat diubah menjadi pointer fungsi. Hal ini membuat hidup JAUH lebih mudah saat beroperasi dengan kode native yang menggunakan pointer fungsi, karena mereka dapat berorientasi objek secara efektif, meskipun programmer asli tidak membuat ketentuan apa pun untuk hal itu.
Delegasi digunakan untuk memanggil metode dengan referensinya. Sebagai contoh:
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();
}
}