NullReferenceException adalah galat runtime yang paling sering ditemui pemrogram C#. Sebelum C# 8, variabel string bisa menampung null tanpa peringatan apa pun, dan kesalahan baru terasa saat program berjalan. Nullable reference types (NRT) memindahkan penemuan masalah itu ke kompilasi: compiler menganalisis data yang mungkin kosong lalu memperingatkan kita sebelum program dijalankan.

Masalah: Null yang Tersembunyi Sampai Runtime #

Method pencarian lazim mengembalikan null saat data tidak ditemukan. Pemanggil yang lupa memeriksa hasilnya langsung mengakses anggota object, dan runtime melempar NullReferenceException. Kode lama tidak punya penanda mana pun yang boleh kosong, sehingga kita harus membaca seluruh implementasi untuk menemukannya.

Mekanisme: Anotasi dan Analisis Compiler #

NRT menambahkan lapisan anotasi di atas tipe referensi. Tipe string? berarti nilai boleh null, sedangkan string tanpa tanda tanya berarti kita berjanji nilainya terisi. Template project .NET modern mengaktifkan analisis ini lewat properti Nullable yang di-set enable. Pelanggaran janji dipertahankan sebagai warning, bukan error, sehingga program tetap bisa dikompilasi dan dijalankan.

Contoh: Mencari Nama Pelanggan #

csharp
Dictionary<string, string> namaPelanggan = new Dictionary<string, string>
{
    ["M-001"] = "Budi Santoso",
    ["M-002"] = "Siti Rahma"
};

string? CariNama(string nomor)
{
    if (namaPelanggan.TryGetValue(nomor, out string? nama))
    {
        return nama;
    }

    return null;
}

string? nama1 = CariNama("M-001");
string? nama2 = CariNama("M-999");

Console.WriteLine($"M-001: {nama1 ?? "(tidak ditemukan)"}");
Console.WriteLine($"M-999: {nama2 ?? "(tidak ditemukan)"}");

if (nama2 is not null)
{
    Console.WriteLine($"Panjang nama: {nama2.Length}");
}
else
{
    Console.WriteLine("Hasil pencarian kosong perlu ditangani");
}

Output yang Dihasilkan:

text
M-001: Budi Santoso
M-999: (tidak ditemukan)
Hasil pencarian kosong perlu ditangani

Mari kita bedah baris demi baris:

  1. string? CariNama(string nomor): Return type string? mengumumkan bahwa hasil pencarian mungkin kosong; pemanggil langsung melihat kontrak itu dari tanda tangan method.
  2. out string? nama: Parameter out milik TryGetValue dianotasi mungkin kosong karena pencarian bisa gagal.
  3. string? nama1 dan string? nama2: Variabel penampung mengikuti anotasi hasil method, sehingga state awalnya mungkin-kosong.
  4. nama1 ?? "(tidak ditemukan)": Titik baca diberi pengganti agar program tetap mencetak sesuatu untuk nomor yang tidak terdaftar.
  5. if (nama2 is not null): Pemeriksaan pola menaikkan state variabel menjadi pasti-terisi di dalam blok, sehingga nama2.Length bebas warning.

Warning yang Muncul Bila Kontrak Dilanggar #

Kode tanpa pemeriksaan, seperti string nama = null; lalu nama.Length, memunculkan dua warning berikut saat dotnet build (path project dipangkas agar ringkas):

text
Program.cs(1,15): warning CS8600: Converting null literal or possible null value to non-nullable type.
Program.cs(2,19): warning CS8602: Dereference of a possibly null reference.

Warning CS8600 menandai penugasan null ke variabel non-nullable, dan CS8602 menandai akses anggota pada nilai yang mungkin kosong. Keduanya adalah sinyal awal yang kita telusuri pada bab Null-State Analysis.