Bagikan melalui


Menggunakan Delegasi (Panduan Pemrograman C#)

Delegasi merupakan jenis yang merangkum metode dengan aman, mirip dengan penunjuk fungsi di C dan C++. Tidak seperti penujuk fungsi, delegasi memiliki sifat yang berorientasi pada objek, terkendali untuk jenis, dan aman. Jenis delegasi ditentukan berdasarkan nama delegasinya. Contoh berikut mendeklarasikan delegasi bernama Callback yang dapat merangkum metode yang mengambil string sebagai argumen dan mengembalikan void:

public delegate void Callback(string message);

Objek delegasi biasanya dibangun dengan memberikan nama metode yang akan dibungkus delegasi, atau dengan ekspresi lambda. Setelah delegasi dibuat dengan cara ini, delegasi dapat dipanggil. Memanggil delegasi memanggil metode yang dilampirkan ke instans delegasi. Parameter yang diteruskan ke delegasi oleh pemanggil akan diteruskan ke metode, dan nilai yang dikembalikan, jika ada, dari metode akan dikembalikan ke pemanggil oleh delegasi. Contohnya:

// Create a method for a delegate.
public static void DelegateMethod(string message)
{
    Console.WriteLine(message);
}
// Instantiate the delegate.
Callback handler = DelegateMethod;

// Call the delegate.
handler("Hello World");

Jenis delegasi berasal dari kelas Delegate yang ada di .NET. Jenis delegasi disegel—tidak dapat diturunkan— dan tidak mungkin memperoleh kelas kustom dari Delegate. Karena delegasi yang dipakai merupakan sebuah objek, delegasi tersebut dapat diteruskan sebagai argumen, atau ditetapkan ke properti. Hal ini memungkinkan metode untuk menerima delegasi sebagai parameter, dan memanggil delegasi di lain waktu. Ini dikenal sebagai panggilan balik asinkron, dan merupakan metode umum untuk memberi tahu pemanggil ketika proses panjang telah selesai. Ketika delegasi digunakan dalam mode ini, kode yang menggunakan delegasi tersebut tidak memerlukan pengetahuan tentang implementasi metode yang digunakan. Fungsionalitasnya mirip dengan antarmuka enkapsulasi yang disediakan antarmuka.

Penggunaan panggilan balik umum lainnya adalah untuk menentukan metode perbandingan kustom dan meneruskan delegasi tersebut ke metode pengurutan. Hal ini memungkinkan kode pemanggil untuk menjadi bagian dari algoritma pengurutan. Metode contoh berikut menggunakan jenis Del sebagai parameter:

public static void MethodWithCallback(int param1, int param2, Callback callback)
{
    callback("The number is: " + (param1 + param2).ToString());
}

Anda kemudian dapat meneruskan delegasi yang dibuat di atas ke metode tersebut:

MethodWithCallback(1, 2, handler);

dan menerima output berikut ini ke konsol:

The number is: 3

Dengan menggunakan delegasi sebagai abstraksi, MethodWithCallback tidak perlu memanggil konsol secara langsung—tidak harus dirancang dengan mempertimbangkan konsol. Hal yang dilakukan MethodWithCallback hanyalah menyiapkan string dan meneruskan string tersebut ke metode lain. Ini sangat kuat karena metode yang didelegasikan dapat menggunakan sejumlah parameter.

Ketika delegasi dibangun untuk membungkus metode instans, delegasi akan mereferensikan instans dan metode. Delegasi tidak memiliki pengetahuan tentang jenis instans selain metode yang dibungkusnya, sehingga delegasi dapat merujuk ke semua jenis objek selama ada metode pada objek yang cocok dengan tanda tangan delegasi. Ketika delegasi dibangun untuk membungkus metode statik, delegasi tersebut hanya akan mereferensikan metode. Pertimbangkan deklarasi berikut:

public class MethodClass
{
    public void Method1(string message) { }
    public void Method2(string message) { }
}

Seiring dengan DelegateMethod statik yang ditunjukkan sebelumnya, kini kita memiliki tiga metode yang dapat dibungkus oleh instans Del.

Delegasi dapat memanggil lebih dari satu metode saat dipanggil. Ini disebut sebagai multicast. Untuk menambahkan metode tambahan ke daftar metode delegasi—daftar pemanggilan—hanya perlu menambahkan dua delegasi dengan menggunakan operator tambahan atau operator penugasan tambahan ('+' atau '+='). Contohnya:

var obj = new MethodClass();
Callback d1 = obj.Method1;
Callback d2 = obj.Method2;
Callback d3 = DelegateMethod;

//Both types of assignment are valid.
Callback allMethodsDelegate = d1 + d2;
allMethodsDelegate += d3;

Pada titik ini, allMethodsDelegate akan berisi tiga metode dalam daftar pemanggilannya—Method1, Method2, dan DelegateMethod. Tiga delegasi asli, d1, d2, dan d3 tetap tidak berubah. Ketika allMethodsDelegate dipanggil, ketiga metode akan dipanggil secara berurutan. Jika delegasi menggunakan parameter referensi, referensi akan diteruskan secara berurutan ke tiap-tiap metode secara bergantian, dan perubahan apa pun pada satu metode akan terlihat oleh metode berikutnya. Ketika salah satu metode melempar pengecualian yang tidak tertangkap di dalam metode, pengecualian tersebut diteruskan ke pemanggil delegasi dan tidak ada metode berikutnya dalam daftar pemanggilan yang akan dipanggil. Jika delegasi memiliki nilai pengembalian dan/atau parameter keluar, delegasi akan mengembalikan nilai dan parameter pengembalian dari metode terakhir yang dipanggil. Untuk menghapus metode dari daftar pemanggilan, gunakan operator pengurangan atau operator penugasan pengurangan (- atau -=). Contohnya:

//remove Method1
allMethodsDelegate -= d1;

// copy AllMethodsDelegate while removing d2
Callback oneMethodDelegate = allMethodsDelegate - d2;

Karena jenis delegasi berasal dari System.Delegate, metode dan properti yang ditentukan oleh kelas tersebut dapat dipanggil pada delegasi. Misalnya, untuk menemukan jumlah metode dalam daftar pemanggilan delegasi, Anda dapat menulis:

int invocationCount = d1.GetInvocationList().GetLength(0);

Delegasi dengan lebih dari satu metode dalam daftar pemanggilan berasal dari MulticastDelegate, yang merupakan subkelas System.Delegate. Kode di atas bekerja di kedua kasus karena kedua kelasnya mendukung GetInvocationList.

Delegasi multicast digunakan secara ekstensif dalam penanganan kejadian. Objek sumber kejadian mengirim pemberitahuan kejadian pada objek penerima yang telah mendaftar untuk menerima kejadian tersebut. Untuk mendaftar kejadian, penerima membuat metode yang dirancang untuk menangani kejadian, lalu membuat delegasi untuk metode tersebut dan meneruskan delegasi ke sumber kejadian. Sumber akan memanggil delegasi saat kejadian terjadi. Delegasi kemudian memanggil metode penanganan kejadian pada penerima dan mengirimkan data kejadian. Jenis delegasi untuk kejadian tertentu ditentukan oleh sumber kejadian. Untuk informasi selengkapnya, lihat Kejadian.

Membandingkan delegasi dari dua jenis berbeda yang ditetapkan saat waktu kompilasi akan mengakibatkan kesalahan kompilasi. Jika instans delegasi secara statik merupakan jenis System.Delegate, perbandingan akan diizinkan, tetapi akan mengembalikan false pada durasi. Contohnya:

delegate void Callback1();
delegate void Callback2();

static void method(Callback1 d, Callback2 e, System.Delegate f)
{
    // Compile-time error.
    //Console.WriteLine(d == e);

    // OK at compile-time. False if the run-time type of f
    // is not the same as that of d.
    Console.WriteLine(d == f);
}

Lihat juga