Anotasi nullability adalah kontrak yang kita tulis pada deklarasi tipe. Kontrak itu dibaca compiler, pembaca kode, dan IDE dengan makna yang sama: nilai ini boleh kosong atau wajib terisi. Bab ini membedah makna anotasi pada anggota class serta konsekuensi compiler bila kontrak dilanggar.

Makna Dua Anotasi Dasar #

DeklarasiJanji kepada compiler
string?Nilai boleh null; pemanggil wajib memeriksa sebelum dipakai
stringNilai dijanjikan terisi; compiler menegur bila kita mengisi null

Kedua anotasi di atas tidak mengubah kode yang dihasilkan; keduanya murni metadata untuk analisis. Kontrak non-nullable menuntut kita mengisi nilai awal, misalnya lewat initializer atau constructor.

Anatomi Anotasi pada Anggota Class #

csharp
public class Pesanan
{
    public string Nomor { get; init; } = "";
    public string? KodeKupon { get; set; }
}

Pesanan pesanan1 = new Pesanan { Nomor = "ORD-1042", KodeKupon = "DISKON10" };
Pesanan pesanan2 = new Pesanan { Nomor = "ORD-1043" };

Console.WriteLine($"Kupon pesanan 1: {pesanan1.KodeKupon}");
Console.WriteLine($"Kupon pesanan 2: {pesanan2.KodeKupon ?? "(tanpa kupon)"}");

string? bacaKupon = pesanan2.KodeKupon;

Console.WriteLine($"Kupon dibaca ulang: {bacaKupon ?? "(kosong)"}");

Output yang Dihasilkan:

text
Kupon pesanan 1: DISKON10
Kupon pesanan 2: (tanpa kupon)
Kupon dibaca ulang: (kosong)

Mari kita bedah baris demi baris:

  1. public string Nomor { get; init; } = "";: Property non-nullable wajib punya nilai awal; initializer "" memenuhi janji sehingga constructor bebas warning.
  2. public string? KodeKupon { get; set; }: Anotasi ? mengizinkan property tetap kosong ketika object dibuat tanpa kupon.
  3. new Pesanan { Nomor = "ORD-1043" }: Object initializer boleh melewatkan KodeKupon karena tipe-nya sudah mengumumkan keboleh-kosongan.
  4. pesanan2.KodeKupon ?? "(tanpa kupon)": Setiap titik baca pada nilai mungkin kosong diberi pengganti agar tampilan tetap jelas.
  5. string? bacaKupon = pesanan2.KodeKupon;: Variabel penampung mewarisi anotasi property, sehingga state-nya juga mungkin-kosong.

Konsekuensi Melanggar Kontrak #

Probe berikut mengisi variabel non-nullable dengan null, meneruskannya sebagai argumen, lalu memanggilnya dengan literal null (path project dipangkas):

text
Program.cs(2,17): warning CS8600: Converting null literal or possible null value to non-nullable type.
Program.cs(5,7): warning CS8604: Possible null reference argument for parameter 'pesan' in 'void Kirim(string pesan)'.
Program.cs(6,7): warning CS8625: Cannot convert null literal to non-nullable reference type.

Warning CS8600 menandai konversi nilai mungkin-kosong ke tipe non-nullable. CS8604 menandai argumen yang mungkin kosong untuk parameter non-nullable, dan CS8625 menandai literal null yang dikirim langsung. Ketiganya menunjuk titik yang sama: janji non-nullable hendak dilanggar.