Saya memiliki kode yang dapat direpresentasikan sebagai:
public class ItemService {
public void DeleteItems(IEnumerable<Item> items)
{
// Save us from possible NullReferenceException below.
if(items == null)
return;
foreach(var item in items)
{
// For the purpose of this example, lets say I have to iterate over them.
// Go to database and delete them.
}
}
}
Sekarang saya bertanya-tanya apakah ini pendekatan yang tepat atau haruskah saya membuang pengecualian. Saya dapat menghindari pengecualian, karena kembali akan sama dengan mengulangi koleksi kosong, artinya, tidak ada kode penting yang dieksekusi, tetapi di sisi lain saya mungkin menyembunyikan masalah di suatu tempat dalam kode, karena mengapa ada orang yang ingin memanggil DeleteItems
dengan null
parameter? Ini mungkin menunjukkan bahwa ada masalah di tempat lain dalam kode.
Ini adalah masalah yang biasanya saya miliki dengan metode dalam layanan, karena kebanyakan dari mereka melakukan sesuatu dan tidak mengembalikan hasilnya, jadi jika seseorang memberikan informasi yang tidak valid maka tidak ada yang dapat dilakukan oleh layanan, sehingga ia kembali.
sumber
Jawaban:
Ini adalah dua pertanyaan yang berbeda.
Haruskah Anda menerima
null
? Itu tergantung pada kebijakan umum Anda tentangnull
basis kode. Menurut pendapat saya, melarang dinull
mana-mana kecuali di mana didokumentasikan secara eksplisit adalah praktik yang sangat baik, tetapi praktik yang lebih baik untuk tetap berpegang pada konvensi yang sudah dimiliki basis kode Anda.Haruskah Anda menerima koleksi kosong? Menurut pendapat saya: YA, tentu saja. Ini jauh lebih banyak upaya untuk membatasi semua penelepon ke koleksi non-kosong daripada melakukan hal yang benar secara matematis - bahkan jika itu mengejutkan beberapa pengembang yang ragu dengan konsep nol.
sumber
AhaINoticedYouPassingInNullException
ketika runtime sudah memberi Anda fasilitas melemparNullReferenceException
untuk Anda, tanpa Anda menulis kode sama sekali. Ada beberapa utilitas (misalnya alat cakupan kode Anda akan memberi tahu Anda apakah Anda memiliki unit test atau tidak untuk memasukkan null pada kasus sebelumnya atau tidak), tetapi tidak ada pengecualian yang harus dicoba / ditangkap pada setiap panggilan ke layanan, karena biasanya kesalahan programmer.NullReferenceException
atau diAhaINoticedYouPassingInNullException
mana pun kecuali pada kode pemulihan bencana tingkat tinggi. Dan penangan pengecualian itu mungkin harus membuat laporan bug :-)null
- apakah pengendali mengandung pelat ketel untuk menangkap dan melanjutkan dalam kasus itu juga?ArgumentNullException
Melempar secara eksplisit lebih baik daripada membiarkan kode interior untuk melemparkanNullReferenceException
- murni melihat pesan pengecualian, jelas bahwa itu adalah kesalahan input daripada kesalahan logika dalam tubuh metode di situs melempar, dan memastikan keluar awal berarti bahwa Anda lebih cenderung meninggalkan data lain dalam keadaan valid daripada bermutasi sebagian dari nol yang tidak terduga nantinya.Nilai Null
Seperti yang sudah dikatakan @KilianFoth, patuhi kebijakan umum Anda. Jika itu dianggap
null
sebagai "singkatan" untuk daftar kosong, lakukan seperti itu.Jika Anda tidak memiliki kebijakan
null
nilai yang konsisten , saya akan merekomendasikan yang berikut:null
harus disediakan untuk mewakili situasi yang tidak dapat diekspresikan oleh tipe "normal", misalnya menggunakannull
untuk mewakili "Saya tidak tahu". Dan itu adalah pilihan yang baik, karena semua orang yang mencoba menggunakan nilai ini secara sembarangan akan mendapatkan pengecualian, yang merupakan hal yang benar.Menggunakan
null
sebagai singkatan untuk daftar kosong tidak memenuhi syarat seperti itu, karena sudah ada representasi yang sempurna, menjadi daftar dengan nol elemen. Dan ini adalah pilihan yang secara teknis buruk, karena memaksa setiap bagian dari kode Anda berurusan dengan daftar untuk memeriksa singkatan yang validnull
.Daftar Kosong
Untuk suatu
DeleteItems()
metode, melewati daftar kosong secara efektif berarti tidak melakukan apa-apa. Saya akan membiarkan itu sebagai argumen, tidak melempar pengecualian, hanya kembali dengan cepat.Tentu saja, penelepon dapat memeriksa elemen nol terlebih dahulu dan melewatkan
DeleteItems()
panggilan dalam kasus itu. Jika kita berbicara tentang API web, untuk alasan efisiensi pemanggil harus melakukan itu untuk menghindari lalu lintas yang tidak perlu dan latensi pulang-pergi. Tapi saya tidak berpikir API Anda harus menegakkan itu.sumber
Melempar pengecualian dan menangani nulls dalam kode panggilan.
Sebagai aturan desain, cobalah untuk menghindari null sebagai nilai parameter. Ini akan mengurangi NullPointerExceptions secara umum, karena nol akan benar-benar menjadi pengecualian.
Selain itu, lihat sisa kode Anda. Jika ini adalah pola umum dalam proyek Anda maka tetaplah konsisten.
sumber
Secara umum, pengecualian melempar harus disediakan untuk situasi luar biasa, yaitu jika kode tidak memiliki tindakan yang wajar untuk dilakukan dalam konteks saat ini.
Anda dapat menerapkan proses pemikiran itu dalam situasi ini. Mengingat ini adalah kelas publik dengan metode publik, Anda memiliki API publik, dan secara teori tidak ada kontrol atas apa yang diteruskan ke sana.
Kode Anda tidak memiliki konteks tentang apa yang memanggilnya (sebagaimana seharusnya), dan tidak ada yang dapat Anda lakukan dengan nilai nol. Ini tentu akan menjadi kandidat untuk
ArgumentNullException
.sumber
null
.null
Anda tidak memiliki koleksi. Jika kode panggilan diharapkan / diharapkan untuk memasok koleksi ke metode, ada sesuatu yang salah, jadi Anda harus melempar. Satu-satunya alasan untuk memperlakukan null sama dengan koleksi kosong adalah jika Anda dapat secara wajar mengharapkan kode panggilan untuk menghasilkan koleksi null. Seperti jawaban lain yang dicatat, sebagian besar waktu, sesuatunull
adalah anomali. Jika Anda memperlakukan ini sama seperti koleksi kosong, Anda berpotensi mengabaikan masalah di tempat lain dalam kode.null
kosong, itu khusus konteks untuk metode ini. Di tempat lain dalam basis kode yang sama, Anda mungkin memilikiIEnumerable
atauIContainer
parameter yang melakukan semacam penyaringan,null
mungkin berarti "tidak ada filter" (izinkan semuanya) sedangkan filter kosong berarti tidak boleh membiarkan apa pun. Dan di tempat lain,null
mungkin secara eksplisit berarti "Saya tidak tahu". Jadi, mengingat itunull
tidak selalu berarti hal yang sama di mana-mana, itu ide yang baik untuk tidak menciptakan makna sama sekali kecuali jika makna itu diperlukan atau setidaknya berguna bagi seseorang.Pertanyaan ini tampaknya bukan tentang pengecualian, tetapi tentang
null
menjadi argumen yang valid.Jadi, pertama dan terpenting Anda harus memutuskan apakah
null
merupakan nilai yang diperbolehkan untuk argumen Anda tentang metode itu. Jika ya, maka Anda tidak perlu pengecualian. Jika tidak, maka Anda perlu pengecualian.Apakah Anda ingin mengizinkan
null
, atau tidak, masih bisa diperdebatkan, seperti yang ditunjukkan oleh banyak dan banyak hit Google tentang itu. Artinya, Anda tidak akan mendapatkan jawaban yang jelas, dan itu tergantung pada pendapat dan tradisi di tempat Anda bekerja.Perselisihan lain adalah apakah fungsi perpustakaan harus benar - benar ketat tentang hal-hal seperti itu, atau serendah mungkin, selama itu tidak berusaha untuk "memperbaiki" parameter yang salah. Bandingkan ini dengan dunia protokol jaringan, transfer surat dll. (Yang merupakan kontrak antarmuka, seperti metode dalam pemrograman). Di sana, biasanya, kebijakannya adalah bahwa pengirim harus sesesuaian mungkin dengan protokol, sementara penerima harus berusaha agar dapat bekerja dengan apa pun yang datang.
Jadi, Anda harus memutuskan: Apakah ini benar-benar tugas metode perpustakaan untuk menegakkan kebijakan yang agak besar seperti
null
penanganan? Terutama jika perpustakaan Anda digunakan oleh orang lain juga (yang mungkin memiliki kebijakan berbeda).Saya mungkin akan berbuat salah di sisi memberikan
null
nilai, mendefinisikan dan mendokumentasikan semantik mereka (yaitu,null = empty array
dalam hal ini), dan tidak melempar pengecualian, kecuali 99% dari kode lain yang serupa (kode gaya "perpustakaan") melakukannya dengan cara lain 'bulat.sumber
null
prinsip menjadi liberal dalam apa yang Anda terima, maka penebangan atau bahkan melempar akan membantu orang-orang yang niatnya harus ketat dalam apa yang mereka lewati, tetapi yang telah mengacaukan kode dan unit mereka menguji sejauh yang mereka lewatinull
.null
, tetapi untuk menyatakannya secara terbuka dalam kontrak metode yang dapat diterima (atau tidak, tergantung pada solusi apa pun yang muncul OP), dan kemudian pertanyaan apakah akan melemparkan pengecualian (atau tidak) memecahkan sendiri.