
Foto oleh Ann H via Pexels
Delegate adalah tipe yang merepresentasikan referensi ke sebuah method, memungkinkan method diperlakukan seperti data yang bisa disimpan dalam variabel, dikirim sebagai parameter, atau dipanggil secara dinamis tanpa mengetahui implementasinya secara langsung saat kode ditulis.
Action dan Func adalah delegate generic bawaan C# yang menghilangkan kebutuhan mendefinisikan delegate custom untuk kasus umum: Action untuk method yang tidak mengembalikan nilai (void), dan Func untuk method yang mengembalikan nilai tertentu.
Event dibangun di atas delegate, menyediakan mekanisme publish-subscribe yang memungkinkan satu class memberi notifikasi ke banyak subscriber lain ketika sesuatu terjadi, pola yang sangat umum dipakai dalam pemrograman berbasis UI maupun arsitektur event-driven.
Mendefinisikan dan Memakai Delegate
Delegate menyimpan referensi method yang bisa diganti-ganti
Action dan Func sebagai Delegate Bawaan
Action untuk void, Func untuk method dengan return value
Event untuk Pola Publish-Subscribe
Event memberi notifikasi ke subscriber saat dipicu
Multicast Delegate untuk Banyak Subscriber
Satu event bisa dipanggil oleh banyak subscriber sekaligus
Memahami Multicast Delegate pada Penanganan Event
Satu event dapat dilanggani oleh lebih dari satu delegate (multicast)
Delegate pada C# bersifat multicast, artinya satu instance delegate dapat menyimpan referensi ke lebih dari satu method sekaligus menggunakan operator +=, dan ketika delegate tersebut dipanggil (Invoke), seluruh method yang terdaftar akan dijalankan secara berurutan sesuai urutan pendaftarannya. Pada contoh di atas, dua handler berbeda yang didaftarkan ke event OnLog sama-sama dijalankan ketika method Proses() memanggil OnLog?.Invoke.
Tanda tanya pada OnLog?.Invoke adalah null-conditional operator yang mencegah NullReferenceException ketika belum ada satu pun subscriber yang mendaftar ke event tersebut, karena nilai default sebuah event sebelum ada yang subscribe adalah null. Tanpa pengecekan ini, memanggil Invoke langsung pada event yang masih null akan menyebabkan aplikasi crash saat runtime.
Action dan Func merupakan delegate generic bawaan .NET yang sering dipakai sebagai pengganti pendeklarasian delegate kustom; Action
Func, Predicate, dan Lambda Expression untuk Komposisi Logika
Func, Predicate, dan Action adalah delegate generic bawaan .NET
Func
Predicate
Lambda expression, ditulis dengan sintaks parameter diikuti tanda panah (=>) dan isi ekspresi atau blok kode, menjadi cara paling ringkas untuk membuat instance dari delegate semacam ini tanpa perlu mendefinisikan method bernama secara terpisah. Komposisi logika menggunakan Func dan Predicate memungkinkan perilaku suatu method diteruskan sebagai argumen ke method lain, sebuah pola yang menjadi dasar dari banyak operator LINQ seperti Where dan Select. Pendekatan komposisi semacam ini membuat logika bisnis yang bersifat kondisional dapat diteruskan sebagai parameter ke method generik, sehingga satu method pemroses data dapat dipakai ulang untuk berbagai kriteria berbeda tanpa perlu menulis ulang method serupa untuk setiap kriteria baru.
Unsubscribe Event Handler untuk Mencegah Memory Leak
Setiap kali sebuah object berlangganan event milik object lain menggunakan operator +=, publisher event secara internal menyimpan referensi ke subscriber tersebut di dalam daftar delegate miliknya. Selama langganan itu tidak dilepas dengan operator -=, garbage collector tidak akan pernah membersihkan subscriber dari memori walaupun objek tersebut sudah tidak digunakan lagi di bagian lain program, karena masih ada referensi aktif yang menahannya tetap hidup selama publisher event masih ada.
Pada contoh di atas, setelah handler dilepas dengan tombol.Diklik -= handler, pemanggilan Klik() berikutnya tidak lagi mencetak apa pun karena tidak ada subscriber yang tersisa pada daftar event tersebut. Kelalaian melepas event handler, khususnya pada aplikasi desktop atau UI dengan banyak komponen yang dibuat dan dihancurkan berulang kali selama siklus hidup aplikasi, adalah penyebab umum memory leak yang sulit dilacak pada aplikasi .NET berskala besar.
Kesalahan Umum yang Sering Terjadi
Lupa Memeriksa Null Sebelum Memanggil Event
Memanggil event secara langsung tanpa operator null-conditional (?.Invoke()) akan menghasilkan NullReferenceException jika belum ada subscriber yang mendaftar sama sekali ke event tersebut.
Lupa Melepas Subscription Event yang Sudah Tidak Dibutuhkan
Subscriber yang tidak melepas langganannya dengan operator -= ketika sudah tidak dibutuhkan bisa menyebabkan memory leak, karena object yang menjadi subscriber tidak bisa dibersihkan garbage collector selama masih terdaftar di event tersebut.
Menggunakan Delegate Custom Padahal Action/Func Sudah Cukup
Mendefinisikan delegate custom untuk kasus sederhana yang sebenarnya sudah bisa ditangani Action atau Func menambah kode yang tidak perlu; delegate custom sebaiknya dibuat hanya ketika nama yang deskriptif benar-benar memberikan nilai tambah pada keterbacaan kode.
Kapan Pendekatan Ini Tidak Cocok Dipakai
Action dan Func memberikan kenyamanan tanpa perlu mendefinisikan delegate baru untuk kasus umum, namun delegate custom dengan nama yang bermakna (seperti Operasi pada contoh di atas) bisa membuat kode lebih mudah dipahami untuk domain bisnis yang spesifik.
Event memberikan enkapsulasi yang lebih baik dibanding delegate publik biasa karena membatasi siapa yang bisa memicu notifikasi tersebut, namun menambah sedikit kompleksitas dibanding pemanggilan method langsung untuk kasus yang sebenarnya tidak membutuhkan pola publish-subscribe.
Ringkasan
Delegate, Action, Func, dan event membentuk fondasi pemrograman fungsional dan event-driven di C#, memungkinkan method diperlakukan sebagai data dan notifikasi dikirim ke banyak subscriber sekaligus. Pilih Action/Func untuk kebutuhan sederhana, dan event ketika benar-benar membutuhkan pola publish-subscribe dengan enkapsulasi yang baik.
Seri Belajar C# Fundamental:
← Sebelumnya: LINQ Dasar untuk Query Collection
→ Selanjutnya: Async Await dan Asynchronous Programming di C#