Delegate dan interface sama-sama memungkinkan perilaku ditukar saat runtime. Diskon potongan harga, misalnya, dapat dimodelkan sebagai delegate Func<int, int> maupun sebagai interface IStrategiDiskon. Keduanya menghasilkan output yang identik, sehingga pertanyaannya bukan soal benar atau salah, melainkan soal bentuk masalah yang sedang kita tangani.
Panduan Memilih #
| Aspek | Delegate | Interface |
|---|---|---|
| Jumlah member | satu method | sekumpulan member |
| State | tidak membawa state sendiri | implementer dapat memiliki field |
| Kegunaan khas | callback, event, strategi satu langkah | kontrak multi member, plugin, dependency injection |
| Deklarasi | tanpa deklarasi tipe baru (Action, Func) | butuh class atau struct implementer |
Aturan praktisnya: satu operasi tertukar-ganti memakai delegate; kelompok operasi yang saling terkait dan butuh state memakai interface.
Perbedaan paling menentukan ada pada state dan jumlah member. Delegate tidak menyimpan data di dalam dirinya; state yang dibutuhkan harus ditangkap lewat closure. Interface, sebaliknya, ditemani class implementer yang bebas menyimpan field, sehingga cocok untuk strategi yang membutuhkan konfigurasi maupun riwayat pemakaian.
Contoh Perbandingan #
interface IStrategiDiskon
{
int Hitung(int total);
}
class DiskonPersen : IStrategiDiskon
{
private readonly int _persen;
public DiskonPersen(int persen) => _persen = persen;
public int Hitung(int total) => total * _persen / 100;
}
static int DiskonMember(int total) => total * 10 / 100;
int total = 200000;
IStrategiDiskon strategiClass = new DiskonPersen(10);
Func<int, int> strategiDelegate = DiskonMember;
Console.WriteLine($"Interface: potongan {strategiClass.Hitung(total)}");
Console.WriteLine($"Delegate : potongan {strategiDelegate(total)}");Output yang Dihasilkan:
Interface: potongan 20000
Delegate : potongan 20000Bedah Kode Baris per Baris #
Mari kita telaah kode di atas:
- Baris 1-4: Interface
IStrategiDiskonmenjanjikan satu methodHitung. Jika kebutuhan berkembang, misalnya menambah deskripsi dan batas periode, interface menampungnya tanpa mengubah pemanggil. - Baris 6-13:
DiskonPersenmenyimpan state_persendi field. State seperti ini tidak dimiliki delegate. - Baris 15:
DiskonMemberadalah method sederhana yang langsung ditugaskan keFunc<int, int>tanpa deklarasi tipe apa pun. - Baris 20-23: Kedua strategi menghasilkan potongan
20000dari total200000, membuktikan keduanya setara untuk kasus satu operasi ini.
Angka 20000 pada kedua baris output sengaja identik: untuk satu operasi murni, delegate dan interface benar-benar setara. Keputusan desain baru bermakna ketika kebutuhan berkembang, dan tabel di atas memberi arah pergeserannya.