Section ini telah memperkenalkan empat cara mendefinisikan tipe: class, struct, record class, dan record struct. Keempatnya menghasilkan tipe yang sah, tetapi semantik penyalinan, penyimpanan, dan kesetaraannya berbeda. Pilihan yang tepat membuat kode lebih mudah dipahami; pilihan yang tergesa menimbulkan kekeliruan salinan data yang sulit dilacak. Bab penutup ini merangkum perbedaannya, lalu memberikan panduan memilih.
Demo Ringkas Empat Tipe #
Contoh berikut menguji keempat tipe dengan skenario yang sama: menyalin variable, mengubah salinannya, dan membandingkan dua instance berisi nilai sama:
public class TitikClass { public int X; public int Y; }
public struct TitikStruct { public int X; public int Y; }
public record TitikRecordClass(int X, int Y);
public record struct TitikRecordStruct(int X, int Y);
TitikClass titikClass = new TitikClass { X = 1, Y = 2 };
TitikClass salinanClass = titikClass;
salinanClass.X = 99;
TitikStruct titikStruct = new TitikStruct { X = 1, Y = 2 };
TitikStruct salinanStruct = titikStruct;
salinanStruct.X = 99;
TitikRecordClass recordA = new TitikRecordClass(1, 2);
TitikRecordClass recordB = new TitikRecordClass(1, 2);
TitikRecordStruct recordStructA = new TitikRecordStruct(1, 2);
TitikRecordStruct recordStructB = new TitikRecordStruct(1, 2);
Console.WriteLine(titikClass.X);
Console.WriteLine(titikStruct.X);
Console.WriteLine(recordA == recordB);
Console.WriteLine(recordStructA == recordStructB);Output yang Dihasilkan:
99
1
True
TrueMari kita bedah hasilnya:
titikClass.Xmenampilkan99:salinanClassmenunjuk object yang sama dengantitikClass, sehingga perubahan pada salinan ikut terbaca dari variable asalnya.titikStruct.Xmenampilkan1:salinanStructmembawa salinan data tersendiri, sehingga perubahan salinan tidak menyentuh variable asalnya.recordA == recordBmenghasilkanTrue: record class membandingkan isi; dua instance terpisah dengan nilai sama dianggap sama.recordStructA == recordStructBmenghasilkanTrue: record struct menggabungkan semantik nilai dan kesetaraan berbasis isi.
Panduan Memilih Tipe #
Tabel berikut merangkum keputusan yang dapat dijadikan pegangan:
| Kebutuhan | Pilihan | Alasan |
|---|---|---|
| Object dengan identitas, perilaku kompleks, atau pewarisan | Class | Reference type dengan masa pakai panjang di heap |
| Data kecil berperan sebagai satu nilai, dibuat dalam jumlah besar | Struct atau record struct | Tanpa alokasi heap, penyalinan cepat |
| Data immutable yang dibandingkan berdasarkan isi | Record class atau record struct | Kesetaraan dan ToString dibangkitkan compiler |
| Data sekali pakai di dalam satu method | Tuple atau anonymous type | Deklarasi ringkas tanpa tipe baru |
| Banyak pilihan yang menyala bersamaan | Flags enum | Satu nilai menyimpan kombinasi bit |
Beberapa aturan praktis menuntun pilihan tersebut:
- Mulailah dari class atau record class untuk tipe domain; pindah ke struct hanya bila data benar-benar kecil dan berperan sebagai nilai.
- Pilih record bila kesetaraan berbasis isi dibutuhkan; hindari menulis
Equalsmanual hanya untuk menggantikan yang sudah dibangkitkan compiler. - Jadikan struct atau record struct bersifat readonly agar risiko perubahan pada salinan tidak mungkin terjadi.
- Pertahankan aturan domain di dalam value object, bukan di method yang tersebar di luar tipe.