Memahami nullability
Jika Anda adalah pengembang .NET, kemungkinan Anda telah menemukan System.NullReferenceException. Ini terjadi pada run time ketika null dereferensi; yaitu, ketika variabel dievaluasi pada runtime, tetapi variabel mengacu pada null. Pengecualian ini sejauh ini adalah pengecualian yang paling umum terjadi dalam ekosistem .NET. Pembuat null, Sir Tony Hoare, menyebut null sebagai "kesalahan miliaran dolar."
Dalam contoh berikut, variabel FooBar ditetapkan ke null dan segera didereferensikan, sehingga menunjukkan masalah:
// Declare variable and assign it as null.
FooBar fooBar = null;
// Dereference variable by calling ToString.
// This will throw a NullReferenceException.
_ = fooBar.ToString();
// The FooBar type definition.
record FooBar(int Id, string Name);
Masalahnya menjadi jauh lebih rumit untuk dikenali sebagai pengembang ketika aplikasi Anda tumbuh dalam ukuran dan kompleksitas. Menemukan potensi kesalahan seperti ini adalah pekerjaan untuk alat, dan pengompilasi C# ada di sini untuk membantu.
Menentukan keamanan null
Istilah keamanan null mendefinisikan serangkaian fitur khusus untuk jenis nullable yang membantu mengurangi jumlah kemungkinan NullReferenceException kemunculan.
Mempertimbangkan contoh sebelumnya FooBar , Anda dapat menghindari NullReferenceException dengan memeriksa apakah fooBar variabel sebelum null mendereferensikannya:
// Declare variable and assign it as null.
FooBar fooBar = null;
// Check for null
if (fooBar is not null)
{
_ = fooBar.ToString();
}
// The FooBar type definition for example.
record FooBar(int Id, string Name);
Untuk membantu dalam mengidentifikasi skenario seperti ini, pengompilasi dapat menyimpulkan niat kode Anda dan menegakkan perilaku yang diinginkan. Namun, ini hanya ketika konteks yang dapat bernilai null diaktifkan. Sebelum membahas konteks nullable, mari kita jelaskan kemungkinan jenis nullable.
Jenis yang dapat diubah ke null
Sebelum C# 2.0, hanya jenis referensi yang dapat diubah ke null. Jenis nilai seperti int atau DateTimetidak bisa menjadi null. Jika jenis ini diinisialisasi tanpa nilai, jenis ini akan kembali ke nilai default-nya. Dalam kasus int, ini adalah 0. Untuk DateTime, itu adalah DateTime.MinValue.
Jenis referensi yang dibuat tanpa nilai awal bekerja secara berbeda. Nilai default untuk semua jenis referensi adalah null.
Pertimbangkan cuplikan kode C# berikut:
string first; // first is null
string second = string.Empty // second is not null, instead it's an empty string ""
int third; // third is 0 because int is a value type
DateTime date; // date is DateTime.MinValue
Dalam contoh sebelumnya:
-
firstadalahnullkarena jenis referensistringdideklarasikan tetapi tidak ada penugasan yang dibuat. -
secondditetapkanstring.Emptyketika dideklarasikan. Objek tidak pernah memiliki penugasannull. -
thirdmeskipun0tidak ditetapkan. Ini adalahstruct(jenis nilai) dan memiliki nilaidefault0. -
datetidak diinisialisasi, tetapi nilainyadefaultadalah System.DateTime.MinValue.
Dimulai dengan C# 2.0, Anda dapat menentukan jenis nilai nullable menggunakan Nullable<T> (atau T? untuk shorthand). Ini memungkinkan jenis nilai menjadi jenis nilai yang dapat diubah ke null. Pertimbangkan cuplikan kode C# berikut:
int? first; // first is implicitly null (uninitialized)
int? second = null; // second is explicitly null
int? third = default; // third is null as the default value for Nullable<Int32> is null
int? fourth = new(); // fourth is 0, since new calls the nullable constructor
Dalam contoh sebelumnya:
-
firstadalahnullkarena jenis nilai yang dapat diubah ke null batal diinisialisasi. -
secondditetapkannullketika dideklarasikan. -
thirdadalahnullseperti nilaidefaultuntukNullable<int>adalahnull. -
fourthadalah0seperti ekspresinew()memanggil konstruktorNullable<int>, danintadalah0secara default.
C# 8.0 memperkenalkan tipe referensi nullable, yang memungkinkan Anda menyampaikan maksud bahwa tipe referensi bisa jadinull atau selalu non-null. Anda mungkin berpikir, "Saya pikir semua jenis referensi nullable!" Anda tidak salah, dan mereka. Fitur ini memungkinkan Anda untuk mengekspresikan niat Anda, yang kemudian coba diberlakukan oleh pengkompilasi. Sintaks T? yang sama mengekspresikan bahwa jenis referensi dimaksudkan agar dapat diubah ke null.
Pertimbangkan cuplikan kode C# berikut:
#nullable enable
string first = string.Empty;
string second;
string? third;
Mengingat contoh sebelumnya, pengkompilasi menyimpulkan niat Anda sebagai berikut:
-
firsttidak pernahnullkarena sudah pasti ditetapkan. -
second, meskipun awalnyanull. Mengevaluasisecondsebelum menetapkan nilai menghasilkan peringatan pengompilasi karena batal diinisialisasi. -
thirdmungkin.nullMisalnya, mungkin menunjuk keSystem.String, tetapi mungkin menunjuk kenull. Salah satu variasi ini dapat diterima. Pengompilasi membantu Anda dengan memperingatkan Anda jika Anda melakukan dereferensithirdtanpa terlebih dahulu memeriksa bahwa itu bukan null.
Penting
Untuk menggunakan fitur jenis referensi nullable seperti yang ditunjukkan di atas, fitur tersebut harus dalam konteks nullable. Hal ini dirincikan di bagian berikutnya.
Konteks yang dapat diubah ke null
Konteks yang dapat diubah ke null memungkinkan kontrol terperinci untuk bagaimana pengompilasi menafsirkan variabel jenis referensi. Ada empat kemungkinan konteks yang dapat diubah ke null:
-
disable: Pengompilasi berperilaku yang mirip dengan C# 7.3 dan yang lebih lama. -
enable: Pengompilasi memungkinkan semua analisis referensi null dan semua fitur bahasa. -
warnings: Pengompilasi melakukan semua analisis null dan memancarkan peringatan ketika kode mungkin melakukan dereferensinull. -
annotations: Pengompilasi tidak melakukan analisis null atau memancarkan peringatan ketika kode mungkin melakukan dereferensinull, tetapi Anda masih dapat membuat anotasi kode Anda menggunakan jenis?referensi yang dapat diubah ke null dan operator null-forgiving (!).
Modul ini dilingkup ke konteks disable atau enable nullable. Untuk informasi selengkapnya, lihat tipe referensi nullable: Konteks Nullable.
Mengaktifkan jenis referensi yang dapat diubah ke null
Dalam file proyek C# (.csproj), tambahkan simpul anak <Nullable> ke <Project> elemen (atau tambahkan ke yang sudah ada <PropertyGroup>). Ini akan menerapkan konteks yang dapat diubah ke null enable ke seluruh proyek.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<!-- Omitted for brevity -->
</Project>
Atau, Anda dapat menetapkan konteks nullable ke file C# menggunakan direktif kompilator.
#nullable enable
Direktif kompilator C# sebelumnya secara fungsional setara dengan konfigurasi proyek, tetapi dicakup ke file tempatnya berada. Untuk informasi selengkapnya, lihat Tipe referensi nullable: Konteks tipe referensi nullable (dokumentasi)
Penting
Konteks nullable diaktifkan dalam file .csproj secara default di semua templat proyek C# yang dimulai dengan .NET 6.0 dan yang lebih besar.
Saat konteks yang dapat diubah ke null diaktifkan, Anda akan mendapatkan peringatan baru. Pertimbangkan contoh sebelumnya FooBar , yang memiliki dua peringatan saat dianalisis dalam konteks nullable:
Baris
FooBar fooBar = null;memiliki peringatan padanullpenugasan: C# Peringatan CS8600: Mengonversi nilai null literal atau kemungkinan nilai null ke tipe yang tidak bisa bernilai null.Garis
_ = fooBar.ToString();juga memiliki peringatan. Kali ini kompilator khawatir bahwafooBarmungkin bernilai null: C# Peringatan CS8602: Dereferensi referensi yang mungkin null.
Penting
Tidak ada jaminan keamanan null yang terjamin, bahkan jika Anda menanggapi dan menghilangkan semua peringatan. Ada beberapa skenario terbatas yang akan melewati analisis kompilator, namun menghasilkan runtime NullReferenceException.
Ringkasan
Dalam unit ini, Anda mempelajari cara mengaktifkan konteks yang dapat diubah ke null dalam C# untuk membantu melindungi dari NullReferenceException. Di unit berikutnya, Anda akan mempelajari lebih lanjut tentang mengekspresikan secara eksplisit niat Anda dalam konteks yang dapat diubah ke null.