
Foto oleh Brett Jordan via Pexels
Constructor adalah method khusus yang dijalankan secara otomatis setiap kali sebuah object dibuat dari class, biasanya dipakai untuk menginisialisasi nilai awal property agar object selalu berada dalam kondisi valid sejak pertama kali dibuat.
Destructor, di sisi lain, adalah method khusus yang dijalankan oleh garbage collector ketika object tidak lagi dipakai dan akan dibersihkan dari memori, meski pada praktiknya destructor jarang dipakai secara langsung di C# karena ada mekanisme lain yang lebih terkendali seperti IDisposable.
Artikel ini membahas cara membuat constructor dengan berbagai variasi parameter, konsep constructor overloading, serta kapan destructor benar-benar dibutuhkan dibanding alternatif lain yang lebih umum dipakai dalam praktik modern.
Constructor Dasar untuk Inisialisasi Object
Constructor memastikan object selalu diinisialisasi dengan nilai valid
Constructor Overloading untuk Fleksibilitas Pembuatan Object
Constructor kedua memanggil constructor pertama dengan this()
Default Constructor dan Parameterless Constructor
Default constructor otomatis tersedia jika tidak ada constructor eksplisit
IDisposable sebagai Alternatif Modern Destructor
IDisposable memberi kontrol eksplisit kapan resource dibersihkan
Constructor Chaining dengan this() dan base()
Constructor chaining menggunakan this() untuk menghindari duplikasi kode
Constructor chaining adalah teknik memanggil satu constructor dari constructor lain dalam class yang sama menggunakan kata kunci this(), seperti pada constructor tanpa parameter Produk() yang meneruskan nilai default ke constructor dengan dua parameter. Teknik ini menghindari duplikasi logika inisialisasi yang sama di beberapa constructor, sehingga jika ada perubahan logika, cukup diubah di satu tempat saja.
Pada konteks inheritance, kata kunci base() digunakan dengan cara serupa namun untuk memanggil constructor milik parent class, dan pemanggilan ini selalu terjadi sebelum isi constructor pada class turunan dijalankan. Jika sebuah class turunan tidak secara eksplisit memanggil base() dengan parameter tertentu, compiler akan otomatis memanggil parameterless constructor milik parent, dan akan menimbulkan compile error jika parent class tidak memiliki constructor tanpa parameter.
Berbeda dengan constructor, destructor pada C# yang dituliskan dengan tanda ~NamaClass tidak dipanggil secara deterministik oleh developer, melainkan dipanggil oleh garbage collector kapan saja objek tersebut dianggap sudah tidak direferensikan lagi. Karena waktu eksekusinya tidak pasti, destructor jarang dipakai untuk melepas resource penting; pola IDisposable dengan using statement jauh lebih umum digunakan untuk tujuan tersebut.
Static Constructor dan Urutan Inisialisasi Field pada Class
Static constructor berjalan tepat sekali, sebelum member static pertama diakses
Static constructor adalah constructor khusus tanpa parameter dan tanpa access modifier yang dijalankan tepat satu kali saja oleh CLR, yaitu pada saat pertama kali class tersebut diakses, baik melalui pembuatan instance maupun melalui pengaksesan member static-nya. Pada contoh di atas, meskipun KonfigurasiAplikasi tidak pernah diinstansiasi dengan new, static constructor tetap terpanggil otomatis begitu baris kode pertama yang mengakses member static-nya dieksekusi.
Static constructor sangat berguna untuk inisialisasi static field yang memerlukan logika lebih kompleks dibanding sekadar assignment sederhana, misalnya membaca nilai dari file konfigurasi atau melakukan kalkulasi awal sebelum field tersebut siap dipakai. Berbeda dengan constructor instance biasa yang bisa dipanggil berkali-kali setiap kali objek baru dibuat, static constructor dijamin oleh CLR hanya dijalankan sekali sepanjang siklus hidup aplikasi, sehingga aman dipakai untuk inisialisasi resource yang mahal secara performa.
Urutan inisialisasi static field mengikuti urutan penulisannya dalam kode sebelum static constructor dijalankan, sehingga field seperti VersiMayor yang memiliki nilai default langsung akan diinisialisasi terlebih dahulu sebelum isi static constructor dieksekusi. Memahami urutan ini penting ketika satu static field bergantung pada nilai static field lain, karena referensi ke field yang belum diinisialisasi akan menghasilkan nilai default tipe tersebut, bukan error, yang terkadang menjadi sumber bug yang sulit dilacak. Jika class memiliki lebih dari satu static constructor secara tidak sengaja melalui inheritance berantai, CLR akan menjamin seluruh static constructor pada hierarki tersebut dijalankan tepat sekali dengan urutan dari parent class menuju class turunan sebelum instance pertama benar-benar dipakai.
Interface IDisposable dan Statement using untuk Resource Cleanup
Interface IDisposable digunakan oleh class yang memegang resource tidak terkelola seperti file handle, koneksi database, atau socket jaringan, yang perlu dilepas secara eksplisit karena garbage collector .NET tidak mengetahui kapan resource eksternal tersebut sebaiknya ditutup, berbeda dengan memori managed biasa yang dibersihkan otomatis. Class yang mengimplementasikan IDisposable wajib menyediakan method Dispose() untuk pembersihan tersebut, biasanya dengan melepas semua resource internal yang dipegangnya satu per satu secara berurutan.
Statement using memastikan method Dispose() dipanggil secara otomatis begitu blok kode selesai dieksekusi, baik berjalan normal maupun karena terjadi exception di tengah jalan, sehingga menghindari kebocoran resource akibat lupa memanggil Dispose() secara manual di setiap kemungkinan jalur keluar method. Pola ini jauh lebih aman dan ringkas dibandingkan mengandalkan try-finally yang ditulis sendiri di setiap tempat pemakaian object yang mengimplementasikan IDisposable, dan sejak C# versi terbaru bahkan tersedia bentuk using declaration tanpa kurung kurawal yang lebih singkat lagi.
Kesalahan Umum yang Sering Terjadi
Mengandalkan Destructor untuk Membersihkan Resource Penting
Destructor dijalankan oleh garbage collector pada waktu yang tidak bisa dipastikan, sehingga resource seperti koneksi database atau file yang perlu ditutup segera sebaiknya memakai IDisposable, bukan mengandalkan destructor yang eksekusinya tertunda.
Lupa Memanggil Constructor Dasar pada Constructor Overload
Tidak memanggil this() pada constructor overload bisa menyebabkan duplikasi logika inisialisasi yang sama ditulis berulang kali di beberapa constructor, meningkatkan risiko inkonsistensi jika salah satu lupa diperbarui saat ada perubahan.
Membuat Terlalu Banyak Constructor Overload
Terlalu banyak variasi constructor overload bisa membingungkan pemanggil tentang constructor mana yang sebaiknya dipakai; pada kasus ini, named parameter atau object initializer sering menjadi alternatif yang lebih jelas.
Kapan Pendekatan Ini Tidak Cocok Dipakai
Constructor overloading memberikan fleksibilitas cara membuat object dengan kombinasi parameter berbeda, namun jika terlalu banyak variasi, justru membingungkan dan sebaiknya dipertimbangkan alternatif seperti builder pattern atau object initializer.
Destructor cocok untuk kasus sangat jarang yang benar-benar butuh pembersihan saat object dihancurkan garbage collector, namun untuk hampir semua kasus pembersihan resource di dunia nyata, IDisposable dengan blok using adalah pilihan yang jauh lebih terkendali dan dapat diprediksi.
Ringkasan
Constructor memastikan object selalu diinisialisasi dalam kondisi valid sejak awal, dengan overloading memberikan fleksibilitas cara pembuatannya. Untuk pembersihan resource, pilih IDisposable dibanding destructor karena memberikan kontrol yang jauh lebih pasti atas kapan proses pembersihan tersebut benar-benar terjadi.
Seri Belajar C# Fundamental:
← Sebelumnya: Method dan Parameter di C#
→ Selanjutnya: Encapsulation dalam OOP C# Secara Mendalam (segera terbit)