Topik ini membahas property, yaitu anggota kelas yang dibaca dan ditulis seperti field tetapi dijalankan sebagai kode. Materinya mencakup auto-property, penggunaan aksesor (accessor, metode pembaca dan penulis nilai di balik property) get dan set, serta setter init-only yang menutup perubahan setelah object selesai dikonstruksi. Setelah topik ini diselesaikan, papan data kelas dapat diekspos dengan aturan akses dan validasi yang terkendali.
Auto-property#
Property menjembatani dua kebutuhan yang saling bertentangan, yaitu sintaks pembacaan field yang ringkas dan kontrol penuh atas aksesnya. Bentuk paling ringkasnya adalah auto-property, yaitu property yang tubuh aksesor kosong sehingga kompilator membuat field penyangga (backing field) secara otomatis. Property seperti ini dideklarasikan dengan { get; set; } dan dipakai persis seperti field biasa.
// Program: auto-property, property terhitung, dan pembaruan nilai melalui setter.
var buku = new Buku
{
Kode = "B-1001",
Judul = "Pengantar Statistika",
Harga = 85000,
Jumlah = 3
};
Console.WriteLine(buku.Judul);
Console.WriteLine(buku.Total);
buku.Harga = 92000;
Console.WriteLine(buku.Total);
class Buku
{
public string Kode { get; init; } = "";
public string Judul { get; set; } = "";
public int Harga { get; set; }
public int Jumlah { get; set; }
public int Total => Harga * Jumlah;
}Pengantar Statistika
255000
276000Property Harga dan Jumlah dibaca dan ditulis melalui sintaks field, tetapi setiap akses melewati aksesor yang dibuat kompilator. Inisialisator = "" pada dua property string mengisi nilai awal sehingga property tidak pernah bernilai null sebelum diisi. Nilai Total yang berubah dari 255000 menjadi 276000 menunjukkan bahwa penugasan buku.Harga = 92000; benar-benar mengubah data object melalui aksesor set.
Aksesor get dan set#
Aksesor get dijalankan ketika property dibaca, sedangkan aksesor set dijalankan ketika property ditulis dan menerima nilai barunya melalui kata kunci value. Bila logika tambahan diperlukan, bentuk auto-property tidak lagi cukup, sehingga field penyangga dideklarasikan sendiri dan kedua aksesor menuliskan logikanya secara eksplisit. Dari luar kelas, aksesnya tidak terbedakan dari pembacaan dan penulisan field biasa.
var kategori = new Kategori();
kategori.Batas = 100;
Console.WriteLine(kategori.Batas);
try
{
kategori.Batas = -5;
}
catch (ArgumentException e)
{
Console.WriteLine($"Ditolak: {e.Message}");
}
class Kategori
{
private int batas;
public int Batas
{
get { return batas; }
set
{
if (value < 0)
{
throw new ArgumentException("Batas tidak boleh negatif");
}
batas = value;
}
}
}100
Ditolak: Batas tidak boleh negatifPenugasan yang sah diteruskan ke field batas, sedangkan penugasan -5 ditolak dengan melemparkan exception ArgumentException sebelum data object tercemar. Inilah keunggulan property atas field publik, yaitu aturan dapat ditegakkan pada satu tempat, dan seluruh penugasan dari bagian mana pun program otomatis melewatinya. Bentuk aksesor ini dipakai pula untuk konversi nilai atau pencatatan, sesuai kebutuhan kelasnya.
Validasi pada aksesor menjadikan property titik pemeriksaan tunggal. Setiap penugasan, baik dari metode kelas itu sendiri maupun dari pemanggil luar, melewati jalur yang sama, sehingga aturan tidak mudah terlewat ketika kode bertambah. Apabila pemeriksaan tidak diperlukan lagi, logikanya cukup dihapus dari satu tempat, dan seluruh pemanggil otomatis mengikuti perubahannya.
Akses kedua aksesor juga dapat dibedakan dengan menuliskan modifier pada salah satunya, misalnya public int Harga { get; private set; } yang terbaca dari mana pun tetapi hanya dapat ditulis dari dalam kelasnya. Pola ini cocok untuk data yang perubahannya harus melalui metode tertentu, karena setter tetap tersedia bagi kelasnya tanpa terbuka bagi pemanggil luar. Kombinasi lain yang lazim adalah protected set, yang membatasi penulisan pada kelas itu sendiri dan kelas turunannya.
Property hanya-baca dan terhitung#
Property yang hanya memiliki aksesor get bersifat hanya-baca dari luar kelas. Penugasannya hanya boleh terjadi di dalam konstruktor atau inisialisator object, sehingga cocok untuk data yang ditetapkan sekali saat object dibuat. Pembacaan dari luar tetap bekerja seperti biasa, sedangkan penugasan dari luar ditolak saat kompilasi.
var acara = new Acara("Rapat Koordinasi");
Console.WriteLine(acara.Nama);
class Acara
{
public string Nama { get; }
public Acara(string nama)
{
Nama = nama;
}
}Rapat KoordinasiSelain menyimpan data, property juga dapat menghitung nilai dari anggota lain. Bentuk public int Total => Harga * Jumlah; pada kelas Buku adalah property terhitung tanpa field penyangga, sehingga setiap pembacaan Total selalu mencerminkan Harga dan Jumlah terbaru. Karena tidak menyimpan apa pun, property semacam ini tidak memiliki aksesor set sama sekali, dan bentuk aksesor lengkapnya berupa get { return Harga * Jumlah; } yang hasilnya identik dengan bentuk ekspresinya.
Setter init-only#
Aksesor init menggantikan set untuk data yang boleh diisi hanya pada saat konstruksi. Property yang menggunakannya dapat ditugaskan di dalam inisialisator object atau konstruktor, tetapi ditolak setelahnya. Kombinasi { get; init; } menghasilkan data yang aman dibagikan karena tidak ada jalur untuk mengubahnya di tengah pemakaian.
// tidak-dijalankan
buku.Kode = "B-2002";Kompilator menolak penugasan tersebut dengan error CS8852: Init-only property or indexer 'Buku.Kode' can only be assigned in an object initializer. Property Kode pada kelas Buku memang menggunakan { get; init; }, sehingga satu-satunya peluang mengisinya adalah pemanggilan new Buku { ... } pada program di awal topik. Apabila nilainya memang harus berubah, perubahannya dinyatakan dengan membuat object baru, bukan dengan membuka aksesor set.
Kesalahan umum#
- Menamai field penyangga sama dengan property-nya. Aksesor yang membaca property itu sendiri tanpa menyentuh field penyangga memanggil dirinya berulang-ulang dan berakhir dengan
StackOverflowException. Beri field penyangga nama berbeda, misalnyabatasuntuk propertyBatas. - Menugaskan kembali property
{ get; init; }. Aksesorinitmenutup penugasan setelah konstruksi, sehingga munculerror CS8852. Gunakan ekspresi penyalinan dengan data yang diperbarui atau buat object baru, dan hindari membukasethanya demi satu penugasan. - Meletakkan logika berat di dalam aksesor. Aksesor dijalankan setiap kali property disentuh, termasuk saat penelusuran (debugging) di debugger, sehingga logika berat menyulitkan pemahaman perilaku kode. Simpan logika berat di metode bernama yang jelas dan biarkan aksesor ringan.
Ringkasan#
- Property dibaca dan ditulis seperti field tetapi dijalankan sebagai kode melalui aksesor
getdanset. - Auto-property meminta kompilator membuat field penyangga, sedangkan aksesor lengkap memungkinkan validasi seperti penolakan nilai negatif.
- Property hanya-baca
{ get; }diisi pada konstruksi, dan property terhitung tanpa penyangga selalu menghitung ulang dari anggota lain. - Aksesor
initmembatasi penugasan pada saat konstruksi saja, sehingga data menjadi tidak dapat diubah setelah object selesai dibuat.
Referensi#
- Properties — Microsoft Learn
— Menjelaskan property, aksesor
getdanset, serta validasi pada aksesor. - Auto-implemented properties — Microsoft Learn — Mendokumentasikan auto-property dan inisialisator property.
- init — Microsoft Learn
— Menjelaskan aksesor
inityang membatasi penugasan pada saat konstruksi.