Nullable reference types memberi manfaat penuh ketika API yang kita tulis jujur tentang keboleh-kosongan. API yang jujur memudahkan compiler menilai setiap pemanggil, sedangkan API yang menipu tipenya memaksa pemanggil memakai akhiran ! atau menambah pemeriksaan ganda. Bab ini merangkum prinsip desain tersebut beserta contoh terpadunya.
Prinsip Desain yang Null-Safe #
- Umumkan hasil yang mungkin kosong lewat return type
T?atau pola Try dengan parameterout. - Jangan mengembalikan
nulldari anggota yang bertipe non-nullable; janji tipe harus sama dengan perilaku. - Wajibkan data penting lewat modifier
requiredalih-alih mengandalkan pemanggil mengisi field kemudian. - Cantumkan atribut nullability untuk pola yang tidak terbaca analisis, seperti
TryGetValue.
Contoh: Direktori Pelanggan #
using System.Diagnostics.CodeAnalysis;
public class DirektoriPelanggan
{
private readonly Dictionary<string, string> data = new Dictionary<string, string>
{
["M-001"] = "Budi Santoso",
["M-002"] = "Siti Rahma"
};
public bool CobaCari(string nomor, [NotNullWhen(true)] out string? nama)
{
return data.TryGetValue(nomor, out nama);
}
public string CariAtauDefault(string nomor)
{
return data.TryGetValue(nomor, out string? nama) ? nama : "(pelanggan baru)";
}
}
public class Produk
{
public required string Nama { get; init; }
public int Stok { get; init; }
}
DirektoriPelanggan direktori = new DirektoriPelanggan();
if (direktori.CobaCari("M-001", out string? nama))
{
Console.WriteLine($"Nama tercatat: {nama.Length} karakter");
}
Console.WriteLine(direktori.CariAtauDefault("M-999"));
Produk produk = new Produk { Nama = "Cokelat Lampung", Stok = 25 };
Console.WriteLine($"{produk.Nama}: stok {produk.Stok}");Output yang Dihasilkan:
Nama tercatat: 12 karakter
(pelanggan baru)
Cokelat Lampung: stok 25Mari kita bedah baris demi baris:
CobaCari(..., out string? nama): Pola Try mengumumkan dua hal sekaligus;[NotNullWhen(true)]menjaminnamaterisi bila returntrue.data.TryGetValue(nomor, out nama): Implementasi mendelegasikan ke dictionary, sehingga janji atribut konsisten dengan perilakuTryGetValuebawaan.Console.WriteLine($"... {nama.Length} ..."): Di dalam blok yang lolos,namadijamin terisi oleh atribut, sehingga aksesLengthbebas warning.CariAtauDefault: Alternatif untuk pemanggil yang tidak butuh cabang; kekosongan diselesaikan di dalam API dengan nilai default yang bermakna.public required string Nama: Modifierrequiredmemaksa object initializer mengisiNama; object initializer tanpaNamaditolak compiler dengan CS9035.
Jebakan yang Sering Ditemui #
Property non-nullable tanpa nilai awal memunculkan warning berikut (path project dipangkas):
Program.cs(7,19): warning CS8618: Non-nullable property 'NamaProyek' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.Pesan CS8618 itu sendiri menyarankan dua jalan keluar: tambahkan modifier required, atau ubah tipe menjadi nullable. Opsi ketiga adalah memberi nilai bawaan pada property, seperti pola = "" pada bab Nullable Annotations.