Rantai data sering kali berisi tautan yang mungkin kosong: pesanan tanpa pembeli, pembeli tanpa kota, atau array yang belum dialokasikan. Memeriksa setiap tautan dengan if membuat kode panjang dan mudah terlewat satu cabang. Operator null-conditional ?. menyingkat pemeriksaan itu menjadi satu karakter yang menyertai setiap tautan berisiko.

Mekanisme Propagasi Null #

Expression x?.Y dibaca: bila x tidak null, hasilnya x.Y; bila x bernilai null, seluruh rantai berhenti dan hasilnya null tanpa mengeksekusi Y. Section Operator sudah memperkenalkan operator ini secara ringkas; di sini kita menekankan dua konsekuensi teknisnya. Pertama, rantai berhenti pada tautan kosong pertama, sehingga tautan setelahnya tidak dievaluasi. Kedua, bila anggota akhir bertipe value type, hasilnya menjadi nullable, misalnya int? untuk Length.

Contoh: Rantai Data Pesanan #

csharp
public record Pelanggan(string Nama, string? Kota);
public record Pesanan(string Nomor, Pelanggan? Pembeli);

Pesanan pesanan1 = new Pesanan("ORD-2001", new Pelanggan("Budi Santoso", "Bandung"));
Pesanan pesanan2 = new Pesanan("ORD-2002", null);

Console.WriteLine($"Pembeli 1: {pesanan1.Pembeli?.Nama ?? "(tanpa pembeli)"}");
Console.WriteLine($"Kota 1: {pesanan1.Pembeli?.Kota ?? "(kota belum diisi)"}");
Console.WriteLine($"Pembeli 2: {pesanan2.Pembeli?.Nama ?? "(tanpa pembeli)"}");

int? panjangKota = pesanan2.Pembeli?.Kota?.Length;

Console.WriteLine($"Panjang kota 2: {panjangKota?.ToString() ?? "null"}");

string[]? daftarGudang = null;

Console.WriteLine($"Gudang pertama: {daftarGudang?[0] ?? "(array masih null)"}");

Output yang Dihasilkan:

text
Pembeli 1: Budi Santoso
Kota 1: Bandung
Pembeli 2: (tanpa pembeli)
Panjang kota 2: null
Gudang pertama: (array masih null)

Mari kita bedah baris demi baris:

  1. record Pesanan(string Nomor, Pelanggan? Pembeli): Anotasi Pelanggan? menyatakan pesanan boleh tanpa pembeli, dan itulah kondisi yang diantisipasi operator ?..
  2. pesanan1.Pembeli?.Nama ?? "(tanpa pembeli)": Pembeli terisi, sehingga rantai berlanjut ke Nama dan mencetak nilai aslinya.
  3. pesanan2.Pembeli?.Nama: Pembeli bernilai null, sehingga Nama tidak dievaluasi dan hasilnya null; operator ?? menggantinya dengan teks penanda.
  4. pesanan2.Pembeli?.Kota?.Length: Setiap tautan membawa ?. sendiri. Rantai berhenti di Pembeli, sehingga hasil bertipe int? bernilai null.
  5. panjangKota?.ToString() ?? "null": Value type int? tidak bisa langsung digabung ?? string, sehingga hasil dikonversi dulu lewat ToString().
  6. daftarGudang?[0]: Bentuk ?[] melindungi pengindeksan; array yang null menghasilkan null, bukan exception.

Padanan dengan Pemeriksaan Manual #

Expression pesanan2.Pembeli?.Nama setara dengan blok if (pesanan2.Pembeli is not null) { ... } yang mengembalikan null pada cabang lain. Perbedaannya terletak pada kepadatan: satu operator menggantikan satu percabangan, dan beberapa operator berderet tetap mudah dibaca.