Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Catatan
Artikel ini mencakup jenis referensi yang dapat diubah ke null. Anda juga dapat mendeklarasikan jenis nilai yang dapat diubah ke null.
Gunakan jenis referensi nullable dalam kode yang berada dalam konteks sadar null. Jenis referensi yang dapat diubah ke null, peringatan analisis statik null, dan operator null-forgiving adalah fitur bahasa opsional. Semua nonaktif secara default. Anda mengontrol konteks nullable di tingkat proyek dengan menggunakan pengaturan build, atau dalam kode dengan menggunakan pragma.
Referensi bahasa C# mendanai versi bahasa C# yang terbaru dirilis. Ini juga berisi dokumentasi awal untuk fitur dalam pratinjau publik untuk rilis bahasa yang akan datang.
Dokumentasi mengidentifikasi fitur apa pun yang pertama kali diperkenalkan dalam tiga versi terakhir bahasa atau dalam pratinjau publik saat ini.
Tip
Untuk menemukan kapan fitur pertama kali diperkenalkan di C#, lihat artikel tentang riwayat versi bahasa C#.
Penting
Semua templat proyek memungkinkan konteks nullable untuk proyek. Proyek yang dibuat dengan template sebelumnya tidak menyertakan elemen ini, dan fitur ini tidak aktif kecuali Anda mengaktifkannya di file proyek atau menggunakan pragma.
Dalam konteks sadar yang dapat diubah ke null:
- Anda harus menginisialisasi variabel jenis
Treferensi dengan nilai non-null, dan Anda tidak pernah dapat menetapkan nilai yang mungkinnull. - Anda dapat menginisialisasi variabel jenis
T?referensi dengannullatau menetapkannull, tetapi Anda harus memeriksanyanullsebelum dereferensi. - Ketika Anda menerapkan operator pengampunan null ke variabel
mjenisT?, seperti dalamm!, variabel dianggap non-null.
Kompilator memberlakukan perbedaan antara jenis T referensi yang tidak dapat diubah ke null dan jenis T? referensi null dengan menggunakan aturan sebelumnya. Variabel jenis T dan variabel jenis T? adalah jenis .NET yang sama. Contoh berikut mendeklarasikan string yang tidak dapat diubah ke null dan string yang dapat diubah ke null, lalu menggunakan operator null-forgiving untuk menetapkan nilai ke string yang tidak dapat diubah ke null:
string notNull = "Hello";
string? nullable = default;
notNull = nullable!; // null forgiveness
Variabel notNull dan nullable keduanya menggunakan jenis .String Karena jenis yang tidak dapat diubah ke null dan dapat diubah ke null keduanya menggunakan jenis yang sama, Anda tidak dapat menggunakan jenis referensi yang dapat diubah ke null di beberapa lokasi. Secara umum, Anda tidak dapat menggunakan jenis referensi nullable sebagai kelas dasar atau antarmuka yang diimplementasikan. Anda tidak dapat menggunakan jenis referensi nullable dalam pembuatan objek atau ekspresi pengujian jenis apa pun. Anda tidak dapat menggunakan tipe referensi yang dapat diubah ke null sebagai jenis ekspresi akses anggota. Contoh berikut menunjukkan konstruksi ini:
public MyClass : System.Object? // not allowed
{
}
var nullEmpty = System.String?.Empty; // Not allowed
var maybeObject = new object?(); // Not allowed
try
{
if (thing is string? nullableString) // not allowed
Console.WriteLine(nullableString);
} catch (Exception? e) // Not Allowed
{
Console.WriteLine("error");
}
Referensi yang dapat diubah ke null dan analisis statik
Contoh di bagian sebelumnya mengilustrasikan sifat jenis referensi yang dapat diubah ke null. Jenis referensi yang dapat diubah ke null bukanlah jenis kelas baru, melainkan anotasi pada jenis referensi yang ada. Kompilator menggunakan anotasi tersebut untuk membantu Anda menemukan potensi kesalahan referensi null dalam kode Anda. Tidak ada perbedaan runtime antara jenis referensi yang tidak dapat diubah ke null dan jenis referensi yang dapat diubah ke null. Kompilator tidak menambahkan pemeriksaan runtime untuk jenis referensi yang tidak dapat diubah ke null. Keuntungannya ada pada analisis waktu kompilasi. Kompilator menghasilkan peringatan yang membantu Anda menemukan dan memperbaiki potensi kesalahan null dalam kode Anda. Anda mendeklarasikan niat Anda, dan kompilator memperingatkan Anda ketika kode Anda melanggar niat tersebut.
Penting
Anotasi referensi yang dapat diubah tidak memperkenalkan perubahan perilaku, tetapi pustaka lain mungkin menggunakan pantulan untuk menghasilkan perilaku runtime yang berbeda untuk jenis referensi nullable dan tidak dapat diubah ke null. Yang perlu diperhatikan, Entity Framework Core membaca atribut nullable. Ini menafsirkan referensi nullable sebagai nilai opsional, dan referensi non-nullable sebagai nilai yang diperlukan.
Dalam konteks yang diaktifkan yang dapat diubah ke null, kompilator melakukan analisis statik pada variabel dari semua jenis referensi, baik yang dapat diubah ke null dan yang tidak dapat diubah ke null. Kompilator melacak status null dari setiap variabel referensi sebagai bukan null atau mungkin null. Status default referensi yang tidak dapat diubah ke null adalah bukan null. Status default referensi yang dapat diubah ke null adalah mungkin null.
Jenis referensi yang tidak dapat diubah ke null harus selalu aman untuk direferensikan karena status null-nya adalah bukan null. Untuk memberlakukan aturan tersebut, kompilator mengeluarkan peringatan jika jenis referensi yang tidak dapat diubah ke null tidak diinisialisasi ke nilai yang bukan null. Anda harus menetapkan variabel lokal tempat Anda mendeklarasikannya. Setiap bidang harus diberi nilai bukan null, dalam penginisialisasi bidang atau setiap konstruktor. Kompilator mengeluarkan peringatan saat referensi yang tidak dapat diubah ke null ditetapkan ke referensi yang statusnya mungkin null. Umumnya, referensi yang tidak dapat diubah ke null bukan nol dan tidak ada peringatan yang dikeluarkan saat Anda mendereferensikan variabel tersebut.
Catatan
Jika Anda menetapkan ekspresi mungkin-null ke jenis referensi yang tidak dapat diubah ke null, pengkompilasi akan menghasilkan peringatan. Kompilator kemudian membuat peringatan untuk variabel tersebut hingga variabel tersebut ditetapkan ke ekspresi bukan null.
Anda dapat menginisialisasi atau menetapkan null ke jenis referensi nullable. Oleh karena itu, analisis statik harus menentukan bahwa suatu variabel bukan null sebelum direferensikan. Jika referensi nullable ditentukan mungkin-null, menetapkannya ke variabel referensi yang tidak dapat diubah ke null menghasilkan peringatan kompilator. Kelas berikut menunjukkan contoh peringatan ini:
public class ProductDescription
{
private string shortDescription;
private string? detailedDescription;
public ProductDescription() // Warning! shortDescription not initialized.
{
}
public ProductDescription(string productDescription) =>
this.shortDescription = productDescription;
public void SetDescriptions(string productDescription, string? details=null)
{
shortDescription = productDescription;
detailedDescription = details;
}
public string GetDescription()
{
if (detailedDescription.Length == 0) // Warning! dereference possible null
{
return shortDescription;
}
else
{
return $"{shortDescription}\n{detailedDescription}";
}
}
public string FullDescription()
{
if (detailedDescription == null)
{
return shortDescription;
}
else if (detailedDescription.Length > 0) // OK, detailedDescription can't be null.
{
return $"{shortDescription}\n{detailedDescription}";
}
return shortDescription;
}
}
Cuplikan berikut menunjukkan di mana compiler mengeluarkan peringatan saat menggunakan kelas ini:
string shortDescription = default; // Warning! non-nullable set to null;
var product = new ProductDescription(shortDescription); // Warning! static analysis knows shortDescription maybe null.
string description = "widget";
var item = new ProductDescription(description);
item.SetDescriptions(description, "These widgets will do everything.");
Contoh sebelumnya menunjukkan bagaimana analisis statik kompilator menentukan status null dari variabel referensi. Kompilator menerapkan aturan bahasa untuk pemeriksaan dan penugasan null untuk menginformasikan analisisnya. Kompilator tidak dapat membuat asumsi tentang semantik metode atau properti. Jika Anda memanggil metode yang melakukan pemeriksaan null, kompilator tidak dapat mengetahui bahwa metode tersebut memengaruhi status null variabel. Anda dapat menambahkan atribut ke API Anda untuk menginformasikan pengkompilasi tentang semantik argumen dan mengembalikan nilai. Banyak API umum di pustaka .NET memiliki atribut ini. Misalnya, pengkompilasi menafsirkan IsNullOrEmpty dengan benar sebagai pemeriksaan null. Untuk informasi selengkapnya tentang atribut yang berlaku untuk analisis statik status null, lihat artikel tentang Atribut yang dapat diubah ke null.
Konteks dapat bernilai null
Konteks nullable menentukan bagaimana pengompilasi menangani anotasi jenis referensi null dan peringatan apa yang dihasilkannya selama analisis status null statis. Konteks nullable berisi dua penanda: pengaturan anotasi dan pengaturan peringatan .
Pengaturan anotasi dan peringatan dinonaktifkan secara default untuk proyek yang ada. Mulai dari .NET 6 (C# 10), kedua flag diaktifkan secara default untuk proyek baru. Alasan adanya dua opsi berbeda untuk pengaturan konteks nullable adalah untuk mempermudah migrasi proyek besar yang sudah ada sebelum pengenalan tipe referensi nullable.
Untuk proyek kecil, Anda dapat mengaktifkan jenis referensi nullable, memperbaiki peringatan, dan melanjutkan. Namun, untuk proyek yang lebih besar dan solusi multi-proyek, proses tersebut mungkin menghasilkan sejumlah besar peringatan. Anda dapat menggunakan pragmas untuk mengaktifkan jenis referensi yang dapat bernilai null per file saat Anda mulai menggunakannya. Fitur baru yang melindungi dari penggunaan System.NullReferenceException dapat mengganggu saat diaktifkan di basis kode yang ada.
- Semua variabel referensi yang diketik secara eksplisit ditafsirkan sebagai jenis referensi yang tidak dapat diubah ke null.
- Arti batasan
classdalam generik berubah menjadi berarti jenis referensi yang tidak dapat diubah ke null. - Peringatan baru dihasilkan karena aturan baru ini.
Konteks anotasi yang dapat diubah ke null menentukan perilaku kompilator. Ada empat kombinasi untuk konteks pengaturan null:
-
keduanya dinonaktifkan: Kodenya nullable-oblivious.
Nonaktifkan mencocokkan perilaku sebelum tipe referensi null diaktifkan; kecuali sintaks baru menghasilkan peringatan alih-alih kesalahan.
- Peringatan nullable dinonaktifkan.
- Semua variabel jenis referensi adalah jenis referensi yang dapat diubah ke null.
- Penggunaan akhiran
?untuk mendeklarasikan jenis referensi yang dapat diubah ke null menghasilkan peringatan. - Anda dapat menggunakan operator pengampunan null,
!, tetapi tidak berpengaruh.
-
keduanya diaktifkan: Pengompilasi mengaktifkan semua analisis referensi null dan seluruh fitur bahasa.
- Semua peringatan baru yang dapat diubah ke null diaktifkan.
- Anda dapat menggunakan akhiran
?untuk mendeklarasikan jenis referensi yang dapat diubah ke null. - Variabel jenis referensi tanpa akhiran
?adalah jenis referensi yang tidak dapat diubah ke null. - Operator pengampunan null menekan peringatan untuk kemungkinan dereferensi
null.
-
peringatan diaktifkan: Kompilator melakukan analisis null secara menyeluruh dan menghasilkan peringatan ketika kode mungkin akan mendereferensi
null.- Semua peringatan baru yang dapat diubah ke null diaktifkan.
- Penggunaan akhiran
?untuk mendeklarasikan jenis referensi yang dapat diubah ke null menghasilkan peringatan. - Semua variabel jenis referensi boleh bernilai null. Namun, anggota memiliki status null dari not null pada kurung kurawal pembuka dari semua metode kecuali dinyatakan dengan akhiran
?. - Anda dapat menggunakan operator pengampunan null,
!.
-
Anotasi diaktifkan: Pengompilasi tidak mengeluarkan peringatan ketika kode mungkin melakukan dereferensi
null, atau saat Anda menetapkan ekspresi mungkin-null ke variabel yang tidak boleh null.- Semua peringatan null baru dinonaktifkan.
- Anda dapat menggunakan akhiran
?untuk mendeklarasikan jenis referensi yang dapat diubah ke null. - Variabel jenis referensi tanpa akhiran
?adalah jenis referensi yang tidak dapat diubah ke null. - Anda dapat menggunakan operator pengampunan null,
!, tetapi tidak berpengaruh.
Anda dapat mengatur konteks anotasi nullable dan konteks peringatan nullable untuk proyek dengan menggunakan <Nullable> elemen dalam file .csproj Anda. Elemen ini mengonfigurasi bagaimana pengkompilasi menginterpretasikan nullability jenis dan peringatan apa yang dipancarkannya. Tabel berikut ini memperlihatkan nilai yang diizinkan dan meringkas konteks yang mereka tentukan.
| Context | Peringatan dereferensi | Peringatan tugas | Jenis referensi |
? akhiran |
! pengoperasi |
|---|---|---|---|---|---|
disable |
Disabled | Disabled | Semua bisa bernilai null | Menghasilkan peringatan | Tidak berpengaruh |
enable |
Enabled | Enabled | Tidak dapat diubah ke null kecuali dinyatakan dengan ? |
Mendeklarasikan tipe yang dapat bernilai null | Menyembunyikan peringatan untuk kemungkinan penugasan null |
warnings |
Enabled | Tidak teraplikasi | Semua nullable, tetapi anggota dianggap tidak-null saat membuka kurung metode | Menghasilkan peringatan | Menyembunyikan peringatan untuk kemungkinan penugasan null |
annotations |
Disabled | Disabled | Tidak dapat diubah ke null kecuali dinyatakan dengan ? |
Mendeklarasikan tipe yang dapat bernilai null | Tidak berpengaruh |
Variabel jenis referensi dalam kode yang dikompilasi dalam konteks yang dinonaktifkan adalah nullable-oblivious. Anda dapat menetapkan null variabel harfiah atau mungkin-null ke variabel yang nullable-oblivious. Namun, status default variabel nullable-oblivious adalah tidak-null.
Pilih pengaturan yang paling sesuai dengan proyek Anda:
- Pilih nonaktifkan untuk proyek lama yang tidak ingin Anda perbarui berdasarkan diagnostik atau fitur baru.
- Pilih peringatan untuk menentukan di mana kode Anda mungkin melemparkan System.NullReferenceException. Anda dapat mengatasi peringatan tersebut sebelum memodifikasi kode untuk mengaktifkan jenis referensi yang tidak dapat diubah ke null.
- Pilih anotasi untuk mengekspresikan niat desain Anda sebelum mengaktifkan peringatan.
- Pilih aktifkan untuk proyek baru dan proyek aktif tempat Anda ingin melindungi dari pengecualian referensi null.
Example:
<Nullable>enable</Nullable>
Anda juga dapat menggunakan arahan untuk mengatur bendera yang sama ini di mana saja dalam kode sumber Anda. Arahan ini paling berguna saat Anda memigrasikan basis kode besar.
-
#nullable enable: Mengatur anotasi dan bendera peringatan ke mengaktifkan. -
#nullable disable: Mengatur anotasi dan bendera peringatan ke menonaktifkan. -
#nullable restore: Memulihkan bendera anotasi dan bendera peringatan ke pengaturan proyek. -
#nullable disable warnings: Mengatur bendera peringatan untuk dinonaktifkan. -
#nullable enable warnings: Mengatur bendera peringatan untuk diaktifkan. -
#nullable restore warnings: Memulihkan bendera peringatan ke pengaturan proyek. -
#nullable disable annotations: Mengatur bendera anotasi untuk dinonaktifkan. -
#nullable enable annotations: Mengatur bendera anotasi untuk diaktifkan. -
#nullable restore annotations: Memulihkan bendera anotasi ke pengaturan proyek.
Untuk baris kode apa pun, Anda dapat mengatur salah satu kombinasi berikut:
| Bendera peringatan | Penanda anotasi | Menggunakan |
|---|---|---|
| proyek bawaan | proyek bawaan | Default |
| aktifkan | nonaktifkan | Memperbaiki peringatan analisis |
| aktifkan | proyek bawaan | Memperbaiki peringatan analisis |
| proyek bawaan | aktifkan | Tambahkan anotasi jenis |
| aktifkan | aktifkan | Kode sudah dimigrasikan |
| nonaktifkan | aktifkan | Melakukan anotasi kode sebelum memperbaiki peringatan |
| nonaktifkan | nonaktifkan | Menambahkan kode lama ke proyek yang dimigrasikan |
| proyek bawaan | nonaktifkan | Jarang |
| nonaktifkan | proyek bawaan | Jarang |
Sembilan kombinasi ini memberi Anda kontrol terperinci atas diagnostik yang dikeluarkan pengkompilasi untuk kode Anda. Anda dapat mengaktifkan lebih banyak fitur di area mana pun yang Anda perbarui, tanpa melihat lebih banyak peringatan yang belum siap Anda atasi.
Penting
Konteks nullable global tidak berlaku untuk file kode yang dihasilkan. Dalam kedua strategi, konteks nullable dinonaktifkan untuk file sumber apa pun yang ditandai sebagai digenerate. Kondisi ini berarti pengompilasi tidak membuat anotasi API apa pun dalam file yang dihasilkan. Pengkompilasi tidak menghasilkan peringatan nullable untuk file yang dihasilkan. File ditandai sebagai dihasilkan dengan salah satu dari empat cara berikut:
- Dalam .editorconfig, tentukan
generated_code = truedi bagian yang berlaku untuk file tersebut. - Memasukkan
<auto-generated>atau<auto-generated/>pada komentar di bagian atas file. Ini bisa berada di baris mana pun dalam komentar itu, tetapi blok komentar harus menjadi elemen pertama dalam file. - Memulai nama file dengan TemporaryGeneratedFile_
- Mengakhiri nama file dengan .designer.cs, .generated.cs, .g.cs, atau .g.i.cs.
Generator dapat ikut serta dengan menggunakan direktif #nullable preprocessor.
Secara default, anotasi nullable dan bendera peringatan berada dalam kondisi dinonaktifkan. Default itu berarti kode Anda yang ada dikompilasi tanpa perubahan dan tanpa menghasilkan peringatan baru. Dimulai dengan .NET 6, proyek baru menyertakan elemen <Nullable>enable</Nullable> di semua templat proyek, menetapkan bendera ini ke diaktifkan.
Opsi ini menyediakan dua strategi berbeda untuk memperbarui basis kode yang ada untuk menggunakan jenis referensi yang dapat bernilai null.
Mengatur konteks yang dapat diubah ke null
Anda dapat mengontrol konteks nullable dengan dua cara. Di tingkat proyek, tambahkan <Nullable>enable</Nullable> pengaturan proyek. Dalam satu file sumber C#, tambahkan #nullable enable pragma untuk mengaktifkan konteks nullable. Untuk informasi selengkapnya, lihat mengatur strategi yang dapat diubah ke null. Sebelum .NET 6, proyek baru menggunakan default, <Nullable>disable</Nullable>. Dimulai dengan .NET 6, proyek baru menyertakan elemen <Nullable>enable</Nullable> dalam file proyek.
Obat Generik
Saat Anda menggunakan parameter jenis, T, sebagai mitra nullable-nya, T?, argumen jenis aktual menentukan bagaimana ditafsirkan ? . Pertimbangkan deklarasi umum berikut:
public class Box<T>
{
public T Contents { get; set; }
}
Karena parameter jenis dapat berdiri untuk jenis referensi atau jenis nilai, arti T? tergantung pada argumen jenis mana yang disediakan pemanggil. Aturan berikut menjelaskan apa yang T? diselesaikan ketika T tidak memiliki batasan:
- Argumen jenis adalah tipe referensi yang tidak dapat diubah ke null. Untuk
Box<string>,TadalahstringdanT?adalahstring?—jenis referensi nullable yang sesuai. - Argumen jenis adalah jenis nilai. Untuk
Box<int>,TadalahintdanT?jugaint—jenis nilai yang sama. Anotasi tidak berpengaruh pada jenis nilai kecuali parameter jenis memiliki batasanstruct, dalam hal iniT?berarti Nullable<T> (int?). - Argumen tipe sudah dapat diubah ke null. Untuk
Box<string?>,Tadalahstring?danT?masihstring?. Anda tidak mendapatkan jenis "doubly nullable".
Batasan membatasi argumen jenis mana yang diizinkan. Mereka juga membiarkan alasan pengkompilasi tentang bagaimana T dapat digunakan:
-
where T : classmemerlukan jenis referensi yang tidak dapat diubah ke null.Box<string>diperbolehkan;Box<string?>menghasilkan peringatan. -
where T : class?memungkinkan tipe referensi nullable atau non-nullable. KeduanyaBox<string>danBox<string?>diperbolehkan. -
where T : structmemerlukan jenis nilai yang tidak dapat diubah ke null.Box<int>diperbolehkan;Box<int?>Tidak. Dengan batasan ini,T?di dalam sarana Nullable<T>generik —untukBox<int>,T?adalahint?. -
where T : notnullmemerlukan referensi atau jenis nilai yang tidak dapat diubah ke null.Box<string>DanBox<int>allah memberikanBox<string?>peringatan kepada orang-orang yang berakal. -
where T : BaseTypememerlukan jenis referensi yang tidak dapat diubah ke null yang berasal dariBaseType. Tambahkan?(where T : BaseType?) untuk memungkinkan jenis turunan nullable juga.
Batasan membantu alasan pengkompilasi tentang bagaimana parameter jenis generik digunakan:
public static T? FirstOrDefault<T>(IEnumerable<T> source)
{
foreach (T item in source)
{
return item;
}
return default;
}
public static void RequireNotNull<T>(T value) where T : notnull
{
ArgumentNullException.ThrowIfNull(value);
}
public static void Generics()
{
string? first = FirstOrDefault<string>([]);
Console.WriteLine(first ?? "<empty>");
RequireNotNull("not null");
}
Spesifikasi bahasa C#
Untuk informasi selengkapnya, lihat bagian Jenis referensi nullable dari spesifikasi bahasa C#.