
Foto oleh Rashed Paykary via Pexels
Record adalah tipe referensi khusus yang diperkenalkan pada C# 9, dirancang khusus untuk merepresentasikan data yang sifatnya immutable (tidak berubah setelah dibuat) dengan kemampuan perbandingan nilai (value equality) bawaan, berbeda dengan class biasa yang secara default membandingkan berdasarkan referensi memori.
Pattern matching adalah kemampuan memeriksa bentuk atau struktur sebuah nilai dan mengekstrak bagian-bagiannya sekaligus dalam satu ekspresi, jauh lebih ringkas dibanding rangkaian if-else atau casting manual yang panjang untuk memeriksa tipe dan nilai suatu object.
Artikel ini membahas cara mendefinisikan record, perbedaannya dengan class biasa dari sisi equality dan immutability, serta berbagai bentuk pattern matching modern yang semakin sering dipakai dalam kode C# terkini.
Mendefinisikan Record dengan Sintaks Ringkas
Record membandingkan berdasarkan nilai, bukan referensi
Immutability dan With Expression
With expression membuat salinan baru dengan sebagian nilai berbeda
Type Pattern dan Property Pattern
Pattern matching memeriksa tipe dan struktur sekaligus
Switch Expression dengan Pattern Matching
Switch expression dengan property pattern untuk logika kompleks
Positional Record dan With-Expression untuk Immutability
Record dengan with-expression menghasilkan salinan baru yang immutable
Record yang diperkenalkan pada C# 9.0 dirancang khusus untuk merepresentasikan data yang bersifat immutable, berbeda dengan class biasa yang propertinya lazim diubah setelah objek dibuat. Positional record seperti Pegawai pada contoh di atas otomatis menghasilkan constructor, property read-only, serta implementasi ToString() yang menampilkan seluruh nilai property secara terbaca, tanpa perlu menuliskan kode boilerplate tersebut secara manual seperti pada class konvensional.
With-expression (with { ... }) memungkinkan pembuatan salinan record baru dengan sebagian nilai property diubah tanpa memengaruhi objek record aslinya, seperti terlihat pada p2 yang hanya mengubah nilai Gaji sementara Nama dan Departemen tetap sama dengan p1. Pola ini sangat berguna untuk merepresentasikan perubahan data seiring waktu tanpa risiko side effect dari mutasi objek yang sedang dipakai di bagian lain program.
Record juga secara otomatis mengimplementasikan value equality, artinya dua instance record dianggap sama (menggunakan operator ==) jika seluruh nilai propertinya identik, berbeda dengan class biasa yang secara default membandingkan berdasarkan reference di memori. Fitur pattern matching modern seperti property pattern (pegawai is { Departemen: "Finance" }) juga bekerja sangat natural dengan record karena strukturnya yang predictable dan immutable.
Record Struct: Menggabungkan Semantik Record dengan Value Type
record struct berperilaku seperti record namun disimpan sebagai value type
Record struct, diperkenalkan pada C# 10, menggabungkan semantik record seperti value equality otomatis, ToString() yang informatif, dan dukungan with-expression, dengan karakteristik penyimpanan memori milik struct yaitu sebagai value type yang disalin sepenuhnya saat di-assign ke variabel lain, berbeda dari record class biasa yang tetap merupakan reference type. Pada contoh di atas, Koordinat cocok dimodelkan sebagai record struct karena merepresentasikan data kecil dan sederhana yang secara konseptual memang berupa nilai, bukan entitas dengan identitas.
Kata kunci readonly yang ditambahkan sebelum record struct membuat seluruh property di dalamnya bersifat init-only secara otomatis, sehingga objek Koordinat benar-benar immutable setelah dibuat, sama seperti record class pada umumnya namun tanpa overhead alokasi pada heap yang biasanya menyertai reference type. With-expression tetap berfungsi normal pada record struct, menghasilkan salinan struct baru dengan sebagian field diubah tanpa memengaruhi struct aslinya.
Pemilihan antara record class dan record struct sebaiknya mengikuti pedoman umum pemilihan class versus struct, yaitu record struct lebih cocok untuk data berukuran kecil yang sering dibuat dan dibuang dalam jumlah besar seperti koordinat geografis atau rentang tanggal, sedangkan record class lebih cocok untuk entitas data yang lebih kompleks atau berukuran besar, karena penyalinan struct besar secara berulang justru dapat menurunkan performa dibanding sekadar menyalin reference pada record class. Tanpa kata kunci readonly, record struct tetap memperbolehkan property diubah melalui setter biasa setelah objek dibuat, sehingga pencantuman readonly secara eksplisit tetap diperlukan ketika sifat immutable benar-benar menjadi kebutuhan utama dari struktur data tersebut.
Pattern Matching Lanjutan: Type Pattern dan Property Pattern
Type pattern pada switch expression memungkinkan percabangan logika berdasarkan tipe data suatu object sekaligus melakukan casting secara implisit, seperti case string s yang langsung memberi variabel s bertipe string tanpa perlu casting manual seperti pada switch statement klasik. Klausa when menambahkan syarat kondisional tambahan di luar pengecekan tipe semata, sehingga satu case bisa memeriksa tipe sekaligus nilai dalam satu baris ekspresi yang ringkas dan mudah dibaca.
Property pattern memperluas kemampuan ini dengan memeriksa nilai dari properti tertentu pada suatu object secara langsung di dalam pattern, tanpa harus mengakses properti tersebut secara terpisah lebih dulu sebelum dibandingkan. Gabungan type pattern dan property pattern membuat logika percabangan berbasis struktur data menjadi lebih ringkas dibandingkan rangkaian if-else dan casting manual yang panjang, terutama ketika menangani banyak kemungkinan bentuk data yang berbeda dalam satu method.
Kesalahan Umum yang Sering Terjadi
Mengira Record Sepenuhnya Menggantikan Class
Record paling cocok untuk data yang sifatnya immutable seperti DTO atau value object, namun untuk entity dengan identitas dan siklus hidup yang kompleks serta behavior yang banyak, class biasa masih lebih sesuai dibanding record.
Mencoba Mengubah Property Record Secara Langsung
Record dengan positional parameter secara default memiliki property init-only, sehingga mencoba mengubahnya langsung setelah object dibuat (p1.Harga = 100) akan menghasilkan error kompilasi; gunakan with expression untuk membuat salinan dengan nilai berbeda.
Tidak Memanfaatkan Pattern Matching yang Sudah Tersedia
Developer yang terbiasa dengan gaya C# lama kadang tetap menulis casting manual dan if-else berantai panjang, padahal pattern matching modern bisa menyederhanakan kode tersebut secara signifikan dengan hasil yang sama.
Kapan Pendekatan Ini Tidak Cocok Dipakai
Record memberikan value equality dan immutability secara otomatis dengan sintaks yang sangat ringkas, sangat cocok untuk DTO, value object, atau data yang dikirim antar layer aplikasi tanpa perlu diubah setelah dibuat.
Pattern matching membuat kode pengecekan kondisi kompleks jauh lebih ringkas dan deklaratif, namun bagi developer yang belum terbiasa dengan sintaksnya, kode yang memakai pattern matching secara intensif bisa terasa kurang familiar dibanding gaya if-else tradisional di awal pembelajaran.
Ringkasan
Record dan pattern matching adalah fitur modern C# yang membuat kode lebih ringkas dan ekspresif: record untuk data immutable dengan value equality, dan pattern matching untuk memeriksa struktur data dengan sintaks yang deklaratif. Manfaatkan keduanya terutama untuk DTO dan logika pengkategorian data yang sering ditemui dalam aplikasi sehari-hari.
Seri Belajar C# Fundamental:
← Sebelumnya: Extension Method di C#
→ Selanjutnya: Best Practice Clean Code di C#