Foto oleh Jorge Jesus via Pexels

NullReferenceException adalah salah satu exception paling umum ditemui developer C#, terjadi ketika kode mencoba mengakses member dari variabel yang nilainya null. C# menyediakan berbagai fitur nullable untuk membantu mencegah masalah ini sejak tahap kompilasi, bukan baru ketahuan saat runtime.

Value type seperti int secara default tidak bisa bernilai null, namun bisa dijadikan nullable dengan menambahkan tanda tanya setelah tipenya (int?), sementara reference type seperti string sejak C# 8 bisa diaktifkan nullable reference types untuk memberi peringatan compiler ketika variabel yang seharusnya tidak null berpotensi diisi null.

Artikel ini membahas cara kerja nullable value type, operator null-conditional dan null-coalescing yang mempermudah penanganan nilai null, serta nullable reference types yang menjadi standar praktik modern di C#.

Nullable Value Type dengan Tanda Tanya

int? memungkinkan value type menampung null

int? umur = null; if (umur.HasValue) Console.WriteLine(umur.Value); else Console.WriteLine("Umur belum diisi"); -- Expected: Umur belum diisi
Menambahkan tanda tanya setelah tipe value type seperti int? atau bool? membuat variabel tersebut bisa menampung null selain nilai normal tipenya. Property HasValue memeriksa apakah variabel benar-benar berisi nilai atau null, dan Value mengambil nilai sebenarnya jika HasValue bernilai true.

Null-Conditional Operator untuk Akses Aman

Operator ?. menghentikan rantai akses jika null ditemukan

Mahasiswa mhs = null; string namaKota = mhs?.Alamat?.Kota; -- Expected: namaKota berisi null, TIDAK melempar -- NullReferenceException meski mhs sendiri null
Operator null-conditional (?.) menghentikan rantai pengaksesan property secara otomatis begitu menemukan nilai null di salah satu titik, mengembalikan null untuk keseluruhan ekspresi alih-alih melempar NullReferenceException, sangat berguna untuk mengakses property bertingkat yang masing-masing berpotensi null.

Null-Coalescing Operator untuk Nilai Default

Operator ?? dan ??= memberi nilai default jika null

string nama = null; string namaTampil = nama ?? "Pengguna Anonim"; Console.WriteLine(namaTampil); -- Expected: Pengguna Anonim nama ??= "Default Lagi"; // null-coalescing assignment Console.WriteLine(nama); -- Expected: Default Lagi
Operator null-coalescing (??) mengembalikan nilai di sisi kanan jika nilai di sisi kiri adalah null, berguna untuk memberi nilai default tanpa menulis if-else eksplisit. Variannya, ??=, langsung meng-assign nilai default tersebut ke variabel jika variabel tersebut masih null, singkatan dari pola if (nama == null) nama = ... yang lebih panjang.

Nullable Reference Types untuk Keamanan Tingkat Compiler

Nullable reference types membedakan string wajib dan string opsional

#nullable enable public class Mahasiswa { public string Nama { get; set; } = string.Empty; // non-nullable, wajib diisi public string? Alamat { get; set; } // nullable, boleh null } // Compiler akan WARNING jika Nama di-assign null secara langsung
Dengan mengaktifkan nullable reference types (#nullable enable atau melalui pengaturan project), compiler bisa membedakan antara string yang wajib diisi (tidak boleh null) dan string? yang memang boleh null, memberikan warning saat kompilasi jika ada potensi assignment null ke variabel yang seharusnya tidak boleh null, membantu menangkap potensi NullReferenceException jauh lebih awal.

Null-Conditional dan Null-Coalescing Operator untuk Null Safety

Null-conditional (?.) dan null-coalescing (??) mencegah NullReferenceException

class Pelanggan { public string? Email { get; set; } } Pelanggan? pelanggan = null; int? panjangEmail = pelanggan?.Email?.Length; Console.WriteLine(panjangEmail); // Output: (kosong, karena null) string emailFinal = pelanggan?.Email ?? "tidak_ada@email.com"; Console.WriteLine(emailFinal); // Output: tidak_ada@email.com

Sejak nullable reference types diperkenalkan pada C# 8.0, tipe referensi seperti string secara default dianggap non-nullable oleh compiler kecuali ditandai eksplisit dengan tanda tanya seperti string?, yang berarti variabel tersebut memang diperbolehkan bernilai null. Ketika fitur ini diaktifkan melalui pengaturan Nullable di file .csproj, compiler akan memberikan warning setiap kali ada kemungkinan null reference yang tidak ditangani, membantu menangkap potensi NullReferenceException sejak tahap kompilasi, bukan saat aplikasi sudah berjalan di production.

Null-conditional operator (?.) memungkinkan pengaksesan member suatu objek yang bisa jadi null tanpa perlu menuliskan pengecekan if secara manual; jika objek di sebelah kiri tanda tersebut bernilai null, seluruh ekspresi akan langsung mengembalikan null tanpa melempar exception, seperti terlihat pada pelanggan?.Email?.Length yang bisa dirangkai berantai untuk beberapa level akses property sekaligus.

Null-coalescing operator (??) menyediakan nilai pengganti ketika ekspresi di sebelah kirinya bernilai null, sementara variannya null-coalescing assignment (??=) langsung menetapkan nilai baru ke suatu variabel hanya jika variabel tersebut saat ini masih null. Kombinasi operator-operator ini membuat penanganan nilai null menjadi jauh lebih ringkas dibanding menuliskan blok if-else bertingkat secara manual di setiap kemungkinan null.

Nullable Value Type (int?) dan Method HasValue, GetValueOrDefault

int? adalah alias dari struct Nullable<int> yang membungkus value type

int? umur = null; Console.WriteLine(umur.HasValue); // Output: False Console.WriteLine(umur.GetValueOrDefault(17)); // Output: 17 umur = 25; if (umur.HasValue) { Console.WriteLine(umur.Value); // Output: 25 } Nullable<int> stok = 0; Console.WriteLine(stok.GetValueOrDefault()); // Output: 0

Tipe value type seperti int, bool, atau DateTime secara bawaan tidak dapat bernilai null karena langsung menyimpan nilainya pada stack, berbeda dengan reference type yang memang mendukung null sejak awal. Untuk mengizinkan value type menampung null, C# menyediakan struct generic Nullable, yang biasa ditulis lebih ringkas dengan tanda tanya setelah nama tipe seperti int? pada variabel umur di atas, yang secara teknis merupakan alias langsung dari Nullable.

Struct Nullable menyediakan property HasValue yang mengembalikan boolean penanda apakah variabel tersebut sedang menyimpan nilai atau sedang bernilai null, serta property Value yang mengembalikan nilai sesungguhnya namun akan melempar InvalidOperationException jika dipanggil saat HasValue bernilai false, sehingga pengecekan HasValue sebaiknya selalu dilakukan sebelum mengakses Value secara langsung untuk menghindari exception yang tidak diinginkan saat runtime.

Method GetValueOrDefault menyediakan cara yang lebih aman untuk mengambil nilai dari Nullable, karena akan mengembalikan nilai default tipe tersebut (seperti 0 untuk int) jika variabel sedang bernilai null, atau menerima parameter opsional sebagai nilai pengganti kustom seperti 17 pada contoh umur di atas. Perbedaan int? dengan null-conditional operator (?.) terletak pada konteksnya, karena int? menangani nullability pada value type itu sendiri, sedangkan ?. menangani pengaksesan member pada reference type yang mungkin null. Kedua mekanisme ini sering dipakai bersamaan pada aplikasi nyata, misalnya ketika membaca kolom nullable dari database yang dipetakan ke property bertipe int? pada entity, lalu diakses dengan aman menggunakan kombinasi HasValue dan GetValueOrDefault sebelum ditampilkan ke pengguna.

Nullable Reference Types (NRT) untuk Keamanan Null pada Compile-Time

#nullable enable public class Pelanggan { public string Nama { get; set; } = ""; public string? Alamat { get; set; } } void CetakAlamat(Pelanggan p) { Console.WriteLine(p.Alamat.Length); // Warning: kemungkinan null Console.WriteLine(p.Alamat?.Length ?? 0); // Aman } // Output (baris kedua): // 0

Nullable Reference Types adalah fitur analisis statis yang diaktifkan dengan #nullable enable atau pengaturan Nullable pada file .csproj, di mana tipe reference seperti string dianggap tidak boleh null secara default, sementara tipe yang ditandai dengan tanda tanya seperti string? secara eksplisit menyatakan bahwa nilainya boleh null dan harus diperiksa dulu sebelum dipakai. Anotasi ini murni berupa petunjuk bagi compiler dan tidak mengubah perilaku program saat runtime sama sekali.

Compiler akan memunculkan warning saat kode mengakses anggota dari tipe nullable tanpa pengecekan terlebih dahulu, seperti p.Alamat.Length pada contoh di atas yang berpotensi melempar NullReferenceException jika Alamat belum diisi, mendorong penggunaan null-conditional operator seperti p.Alamat?.Length atau pengecekan eksplisit sebelum akses. Fitur ini membantu menangkap potensi kesalahan terkait null sejak tahap kompilasi, jauh sebelum kode benar-benar dijalankan di lingkungan production dan menyebabkan aplikasi berhenti tiba-tiba tanpa peringatan sebelumnya.

Kesalahan Umum yang Sering Terjadi

Mengakses .Value pada Nullable Tanpa Memeriksa HasValue

Mengakses .Value pada nullable value type yang ternyata bernilai null akan melempar InvalidOperationException, sehingga selalu periksa HasValue atau gunakan operator ?? terlebih dahulu sebelum mengakses Value secara langsung.

Mengabaikan Warning Nullable Reference Types

Warning yang muncul dari nullable reference types sering diabaikan oleh developer yang terburu-buru, padahal warning tersebut sebenarnya menandai potensi NullReferenceException nyata yang akan terjadi di production jika tidak ditangani.

Menggunakan Null-Forgiving Operator Secara Sembarangan

Operator null-forgiving (!) yang memaksa compiler mengabaikan kemungkinan null pada suatu ekspresi sebaiknya hanya dipakai ketika benar-benar yakin nilai tersebut tidak akan null, bukan sebagai cara cepat menghilangkan warning tanpa analisis yang tepat.

Kapan Pendekatan Ini Tidak Cocok Dipakai

Fitur nullable memberikan jaring pengaman yang kuat terhadap NullReferenceException, namun menambah sedikit verbositas kode terutama saat menangani banyak kemungkinan null secara eksplisit di berbagai tempat.

Mengaktifkan nullable reference types pada project lama yang belum terbiasa dengan anotasi nullable bisa menghasilkan banyak warning sekaligus yang perlu waktu untuk dibereskan, namun investasi ini sepadan karena secara signifikan mengurangi bug null reference di production dalam jangka panjang.

Ringkasan

Fitur nullable di C#, mulai dari nullable value type, operator null-conditional dan null-coalescing, hingga nullable reference types, bekerja sama untuk mengurangi risiko NullReferenceException. Manfaatkan fitur-fitur ini secara konsisten, terutama nullable reference types pada project baru, untuk menangkap potensi masalah null sejak tahap kompilasi.

Seri Belajar C# Fundamental:

← Sebelumnya: Async Await dan Asynchronous Programming di C#

→ Selanjutnya: Extension Method di C#