Pembaruan: Dimulai dengan Visual Studio 2015, kompiler C # (versi bahasa 6) sekarang mengenali ?.
operator, yang membuat "pemeriksaan nol dalam" menjadi mudah. Lihat jawaban ini untuk detailnya.
Selain mendesain ulang kode Anda, seperti yang
disarankan oleh jawaban yang dihapus ini , pilihan lain (walaupun mengerikan) adalah menggunakan try…catch
blok untuk melihat apakah NullReferenceException
terjadi suatu saat selama pencarian properti mendalam tersebut.
try
{
var x = cake.frosting.berries.loader;
...
}
catch (NullReferenceException ex)
{
// either one of cake, frosting, or berries was null
...
}
Saya pribadi tidak akan melakukan ini karena alasan berikut:
- Itu tidak terlihat bagus.
- Ini menggunakan penanganan pengecualian, yang harus menargetkan situasi luar biasa dan bukan sesuatu yang Anda harapkan akan sering terjadi selama operasi normal.
NullReferenceException
Mungkin seharusnya tidak pernah ditangkap secara eksplisit. (Lihat pertanyaan ini .)
Jadi apakah mungkin menggunakan beberapa metode ekstensi atau apakah itu fitur bahasa, [...]
Ini hampir pasti harus menjadi fitur bahasa (yang tersedia dalam C # 6 dalam bentuk .?
dan ?[]
operator), kecuali C # sudah memiliki evaluasi malas yang lebih canggih, atau kecuali jika Anda ingin menggunakan refleksi (yang mungkin juga bukan ide yang bagus untuk alasan kinerja dan keamanan tipe).
Karena tidak ada cara untuk hanya beralih cake.frosting.berries.loader
ke fungsi (itu akan dievaluasi dan melempar pengecualian referensi nol), Anda harus menerapkan metode pencarian umum dengan cara berikut: Dibutuhkan objek dan nama properti untuk menengadah:
static object LookupProperty( object startingPoint, params string[] lookupChain )
{
// 1. if 'startingPoint' is null, return null, or throw an exception.
// 2. recursively look up one property/field after the other from 'lookupChain',
// using reflection.
// 3. if one lookup is not possible, return null, or throw an exception.
// 3. return the last property/field's value.
}
...
var x = LookupProperty( cake, "frosting", "berries", "loader" );
(Catatan: kode diedit.)
Anda dengan cepat melihat beberapa masalah dengan pendekatan seperti itu. Pertama, Anda tidak mendapatkan keamanan tipe apa pun dan kemungkinan tinju nilai properti dari tipe sederhana. Kedua, Anda dapat kembali null
jika terjadi kesalahan, dan Anda harus memeriksa ini di fungsi panggilan Anda, atau Anda melempar pengecualian, dan Anda kembali ke tempat Anda memulai. Ketiga, mungkin lambat. Keempat, terlihat lebih buruk dari apa yang Anda mulai.
[...], atau itu hanya ide yang buruk?
Saya akan tetap dengan:
if (cake != null && cake.frosting != null && ...) ...
atau pergi dengan jawaban di atas oleh Mehrdad Afshari.
PS: Dulu ketika saya menulis jawaban ini, saya jelas tidak mempertimbangkan pohon ekspresi untuk fungsi lambda; lihat misalnya jawaban @driis untuk solusi ke arah ini. Ini juga didasarkan pada semacam refleksi dan karenanya mungkin tidak berkinerja sebaik solusi yang lebih sederhana ( if (… != null & … != null) …
), tetapi mungkin dinilai lebih baik dari sudut pandang sintaksis.