Itu semacam pertanyaan umum (tapi saya menggunakan C #), apa cara terbaik (praktik terbaik), apakah Anda mengembalikan koleksi kosong atau kosong untuk metode yang memiliki koleksi sebagai tipe pengembalian?
c#
collections
Omu
sumber
sumber
Jawaban:
Koleksi kosong. Selalu.
Ini menyebalkan:
Ini dianggap sebagai praktik terbaik untuk TIDAK PERNAH kembali
null
ketika mengembalikan koleksi atau dihitung. SELALU mengembalikan enumerable / koleksi kosong. Ini mencegah omong kosong yang disebutkan di atas, dan mencegah mobil Anda diganggu oleh rekan kerja dan pengguna kelas Anda.Saat berbicara tentang properti, selalu atur properti Anda sekali dan lupakan
Di .NET 4.6.1, Anda bisa memadatkan ini cukup banyak:
Saat berbicara tentang metode yang mengembalikan enumerable, Anda dapat dengan mudah mengembalikan enumerable kosong daripada
null
...Menggunakan
Enumerable.Empty<T>()
dapat dilihat sebagai lebih efisien daripada mengembalikan, misalnya, koleksi atau array kosong baru.sumber
IEnumerable
atauICollection
tidak. Ngomong-ngomong, jika kamu memilih sesuatu yang bertipeICollection
mereka juga kembalinull
... Aku ingin mereka mengembalikan koleksi kosong, tapi aku bertemu mereka kembalinull
, jadi kupikir aku akan menyebutkannya di sini. Saya akan mengatakan bahwa koleksi default enumerable kosong, bukan null. Saya tidak tahu itu subjek yang sensitif.Dari Framework Design Guidelines 2nd Edition (hal 256):
Inilah artikel menarik lainnya tentang manfaat tidak mengembalikan nol (saya mencoba menemukan sesuatu di blog Brad Abram, dan dia menautkan ke artikel itu).
Sunting - seperti Eric Lippert sekarang telah mengomentari pertanyaan awal, saya juga ingin menautkan ke artikelnya yang sangat bagus .
sumber
Tergantung pada kontrak Anda dan kasing beton Anda . Umumnya yang terbaik adalah mengembalikan koleksi kosong , tetapi kadang-kadang ( jarang ):
null
mungkin berarti sesuatu yang lebih spesifik;null
.Beberapa contoh nyata:
null
artinya elemen tersebut hilang, sementara koleksi kosong akan membuat redundan (dan mungkin salah)<collection />
sumber
Ada satu hal lain yang belum disebutkan. Pertimbangkan kode berikut:
Bahasa C # akan mengembalikan enumerator kosong saat memanggil metode ini. Oleh karena itu, agar konsisten dengan desain bahasa (dan, dengan demikian, harapan programmer) koleksi kosong harus dikembalikan.
sumber
Kosong jauh lebih ramah konsumen.
Ada metode yang jelas untuk membuat enumerable kosong:
sumber
Tampak bagi saya bahwa Anda harus mengembalikan nilai yang secara semantik benar dalam konteks, apa pun itu. Aturan yang mengatakan "selalu kembalikan koleksi kosong" tampaknya sedikit sederhana bagi saya.
Misalkan dalam, katakanlah, sebuah sistem untuk rumah sakit, kami memiliki fungsi yang seharusnya mengembalikan daftar semua rawat inap sebelumnya selama 5 tahun terakhir. Jika pelanggan belum masuk rumah sakit, masuk akal untuk mengembalikan daftar kosong. Tetapi bagaimana jika pelanggan membiarkan bagian dari formulir penerimaan itu kosong? Kami membutuhkan nilai yang berbeda untuk membedakan "daftar kosong" dari "tidak ada jawaban" atau "tidak tahu". Kita bisa melempar pengecualian, tetapi itu tidak selalu merupakan kondisi kesalahan, dan itu tidak serta merta membuat kita keluar dari aliran program normal.
Saya sering frustrasi oleh sistem yang tidak dapat membedakan antara nol dan tidak ada jawaban. Saya sudah beberapa kali di mana suatu sistem meminta saya untuk memasukkan beberapa angka, saya memasukkan nol, dan saya mendapatkan pesan kesalahan yang memberi tahu saya bahwa saya harus memasukkan nilai dalam bidang ini. Saya baru saja melakukannya: Saya memasukkan nol! Tetapi itu tidak akan menerima nol karena tidak dapat membedakannya dari tidak ada jawaban.
Balas ke Saunders:
Ya, saya berasumsi bahwa ada perbedaan antara "Orang tidak menjawab pertanyaan" dan "Jawabannya nol." Itulah poin paragraf terakhir dari jawaban saya. Banyak program tidak dapat membedakan "tidak tahu" dari kosong atau nol, yang menurut saya merupakan potensi kesalahan serius. Sebagai contoh, saya berbelanja untuk rumah sekitar setahun yang lalu. Saya pergi ke situs web real estat dan ada banyak rumah terdaftar dengan harga $ 0. Kedengarannya cukup bagus bagi saya: Mereka memberikan rumah-rumah ini secara gratis! Tapi saya yakin kenyataan menyedihkannya adalah mereka belum memasukkan harganya. Dalam hal ini Anda dapat berkata, "Yah, SANGAT nol berarti mereka tidak memasukkan harga - tidak ada yang akan memberikan rumah secara gratis." Tetapi situs tersebut juga mencantumkan harga jual dan permintaan rata-rata rumah di berbagai kota. Saya bertanya-tanya apakah rata-rata tidak termasuk nol, sehingga memberikan rata-rata rendah yang salah untuk beberapa tempat. yaitu berapa rata-rata $ 100.000; $ 120.000; dan "tidak tahu"? Secara teknis jawabannya adalah "tidak tahu". Yang mungkin ingin kami lihat adalah $ 110.000. Tapi yang mungkin akan kita dapatkan adalah $ 73.333, yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tapi saya yakin Anda pernah melihatnya melakukannya untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"? sehingga memberikan rata-rata rendah yang salah untuk beberapa tempat. yaitu berapa rata-rata $ 100.000; $ 120.000; dan "tidak tahu"? Secara teknis jawabannya adalah "tidak tahu". Yang mungkin ingin kami lihat adalah $ 110.000. Tapi yang mungkin akan kita dapatkan adalah $ 73.333, yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tetapi saya yakin Anda telah melihatnya dilakukan untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"? sehingga memberikan rata-rata rendah yang salah untuk beberapa tempat. yaitu berapa rata-rata $ 100.000; $ 120.000; dan "tidak tahu"? Secara teknis jawabannya adalah "tidak tahu". Yang mungkin ingin kami lihat adalah $ 110.000. Tapi yang mungkin akan kita dapatkan adalah $ 73.333, yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tetapi saya yakin Anda telah melihatnya dilakukan untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"? yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tapi saya yakin Anda pernah melihatnya melakukannya untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"? yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tetapi saya yakin Anda telah melihatnya dilakukan untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"?
RE memiliki dua fungsi terpisah, "apakah ada?" dan "jika demikian, apa itu?" Ya, Anda tentu bisa melakukan itu, tetapi mengapa Anda mau? Sekarang program panggilan harus membuat dua panggilan, bukan satu. Apa yang terjadi jika seorang programmer gagal memanggil "any?" dan langsung menuju ke "apa itu?" ? Apakah program akan mengembalikan nol salah arah? Melempar pengecualian? Kembalikan nilai yang tidak ditentukan? Ini menciptakan lebih banyak kode, lebih banyak pekerjaan, dan lebih banyak kesalahan potensial.
Satu-satunya manfaat yang saya lihat adalah memungkinkan Anda untuk mematuhi aturan arbitrer. Apakah ada manfaat dari aturan ini yang membuatnya sepadan dengan kesulitan mematuhinya? Jika tidak, mengapa repot-repot?
Balas ke Jammycakes:
Pertimbangkan seperti apa kode yang sebenarnya. Saya tahu pertanyaan kata C # tetapi maafkan saya jika saya menulis Java. C # saya tidak terlalu tajam dan prinsipnya sama.
Dengan pengembalian nol:
Dengan fungsi terpisah:
Ini sebenarnya satu atau dua kode lebih sedikit dengan pengembalian nol, jadi tidak lebih banyak beban pada pemanggil, itu lebih sedikit.
Saya tidak melihat bagaimana ini menciptakan masalah KERING. Bukannya kita harus melakukan panggilan dua kali. Jika kita selalu ingin melakukan hal yang sama ketika daftar tidak ada, mungkin kita bisa mendorong penanganan ke fungsi daftar daripada meminta penelepon melakukannya, dan dengan demikian menempatkan kode di penelepon akan menjadi pelanggaran KERING. Tapi kita hampir pasti tidak ingin selalu melakukan hal yang sama. Dalam fungsi di mana kita harus memiliki daftar untuk diproses, daftar yang hilang adalah kesalahan yang mungkin menghentikan pemrosesan. Tetapi pada layar edit, kami pasti tidak ingin menghentikan pemrosesan jika mereka belum memasukkan data: kami ingin mereka memasukkan data. Jadi penanganan "no list" harus dilakukan di level pemanggil dengan satu atau lain cara. Dan apakah kita melakukan itu dengan pengembalian nol atau fungsi terpisah tidak ada bedanya dengan prinsip yang lebih besar.
Tentu, jika penelepon tidak memeriksa null, program bisa gagal dengan pengecualian null-pointer. Tetapi jika ada fungsi "punya" yang terpisah dan penelepon tidak memanggil fungsi itu tetapi secara buta memanggil fungsi "dapatkan daftar", lalu apa yang terjadi? Jika ia melempar pengecualian atau gagal, yah, itu hampir sama dengan apa yang akan terjadi jika ia mengembalikan nol dan tidak memeriksanya. Jika mengembalikan daftar kosong, itu hanya salah. Anda gagal membedakan antara "Saya punya daftar dengan nol elemen" dan "Saya tidak punya daftar". Ini seperti mengembalikan nol untuk harga ketika pengguna tidak memasukkan harga apa pun: itu hanya salah.
Saya tidak melihat bagaimana melampirkan atribut tambahan ke koleksi membantu. Penelepon masih harus memeriksanya. Bagaimana itu lebih baik daripada memeriksa null? Sekali lagi, hal terburuk yang dapat terjadi adalah programmer lupa untuk memeriksanya, dan memberikan hasil yang salah.
Sebuah fungsi yang mengembalikan null bukanlah kejutan jika programmer akrab dengan konsep makna nol "tidak memiliki nilai", yang saya pikir setiap programmer yang kompeten seharusnya pernah mendengar, apakah dia pikir itu ide yang bagus atau tidak. Saya pikir memiliki fungsi terpisah lebih merupakan masalah "kejutan". Jika seorang programmer tidak terbiasa dengan API, ketika dia menjalankan tes tanpa data, dia akan dengan cepat menemukan bahwa kadang-kadang dia kembali nol. Tetapi bagaimana ia menemukan keberadaan fungsi lain kecuali jika terlintas dalam benaknya bahwa mungkin ada fungsi semacam itu dan ia memeriksa dokumentasinya, dan dokumentasinya lengkap dan dapat dipahami? Saya lebih suka memiliki satu fungsi yang selalu memberi saya respons yang bermakna, daripada dua fungsi yang harus saya ketahui dan ingat untuk memanggil keduanya.
sumber
Jika koleksi kosong masuk akal secara semantik, itulah yang saya inginkan untuk dikembalikan. Mengembalikan koleksi kosong untuk
GetMessagesInMyInbox()
berkomunikasi "Anda benar-benar tidak memiliki pesan di kotak masuk Anda", sedangkan pengembaliannull
mungkin berguna untuk berkomunikasi bahwa data yang tidak memadai tersedia untuk mengatakan seperti apa daftar yang mungkin dikembalikan seharusnya terlihat.sumber
null
nilai pasti tidak tampak masuk akal, saya berpikir secara umum tentang hal itu. Pengecualian juga bagus untuk mengomunikasikan fakta bahwa ada yang tidak beres, tetapi jika "data tidak mencukupi" yang dimaksud sesuai dengan yang diharapkan, maka melemparkan pengecualian akan ada desain yang buruk. Saya agak memikirkan skenario di mana itu sangat mungkin dan tidak ada kesalahan sama sekali untuk metode untuk kadang-kadang tidak dapat menghitung respons.Mengembalikan null bisa lebih efisien, karena tidak ada objek baru yang dibuat. Namun, itu juga sering membutuhkan
null
pemeriksaan (atau penanganan pengecualian).Secara semantik,
null
dan daftar kosong tidak berarti hal yang sama. Perbedaannya halus dan satu pilihan mungkin lebih baik daripada yang lain dalam hal tertentu.Apa pun pilihan Anda, dokumentasikan untuk menghindari kebingungan.
sumber
Orang dapat berargumen bahwa alasan di balik Pola Objek Null mirip dengan yang mendukung pengembalian koleksi kosong.
sumber
Tergantung situasinya. Jika ini adalah kasus khusus, maka kembalikan nol. Jika fungsi hanya mengembalikan koleksi kosong, maka jelas mengembalikan itu ok. Namun, mengembalikan koleksi kosong sebagai kasus khusus karena parameter yang tidak valid atau alasan lain BUKAN ide yang baik, karena menutupi kondisi kasus khusus.
Sebenarnya, dalam hal ini saya biasanya lebih suka melempar pengecualian untuk memastikan itu BENAR-BENAR tidak diabaikan :)
Mengatakan itu membuat kode lebih kuat (dengan mengembalikan koleksi kosong) karena mereka tidak harus menangani kondisi nol adalah buruk, karena hanya menutupi masalah yang harus ditangani oleh kode panggilan.
sumber
Saya berpendapat bahwa
null
itu tidak sama dengan koleksi kosong dan Anda harus memilih yang terbaik mewakili apa yang Anda kembalikan. Dalam kebanyakan kasusnull
tidak ada apa-apa (kecuali dalam SQL). Koleksi kosong adalah sesuatu, meskipun sesuatu yang kosong.Jika Anda harus memilih satu atau yang lain, saya akan mengatakan bahwa Anda harus cenderung ke koleksi kosong daripada nol. Tetapi ada kalanya koleksi kosong tidak sama dengan nilai nol.
sumber
Pikirkan selalu dalam mendukung klien Anda (yang menggunakan api Anda):
Mengembalikan 'null' sangat sering membuat masalah dengan klien yang tidak menangani pemeriksaan nol dengan benar, yang menyebabkan NullPointerException selama runtime. Saya telah melihat kasus-kasus dimana pemeriksaan nol yang hilang memaksa masalah produksi prioritas (klien menggunakan foreach (...) pada nilai nol). Selama pengujian masalah tidak terjadi, karena data yang dioperasikan sedikit berbeda.
sumber
Saya ingin memberi penjelasan di sini, dengan contoh yang sesuai.
Pertimbangkan sebuah kasus di sini ..
Di sini Pertimbangkan fungsi yang saya gunakan ..
Saya dapat dengan mudah menggunakan
ListCustomerAccount
danFindAll
bukannya.,CATATAN: Karena AccountValue tidak
null
, fungsi Sum () tidak akan kembalinull
., Karena itu saya dapat menggunakannya secara langsung.sumber
Kami melakukan diskusi ini di antara tim pengembangan di tempat kerja sekitar seminggu yang lalu, dan kami hampir dengan suara bulat pergi untuk pengumpulan kosong. Satu orang ingin mengembalikan nol untuk alasan yang sama yang disebutkan Mike di atas.
sumber
Koleksi Kosong. Jika Anda menggunakan C #, asumsinya adalah memaksimalkan sumber daya sistem tidak penting. Meskipun kurang efisien, pengembalian Empty Collection jauh lebih nyaman bagi para programmer yang terlibat (untuk alasan yang akan diuraikan di atas).
sumber
Mengembalikan koleksi kosong lebih baik dalam banyak kasus.
Alasannya adalah kemudahan implementasi penelepon, kontrak yang konsisten, dan implementasi yang lebih mudah.
Jika metode mengembalikan nol untuk menunjukkan hasil kosong, pemanggil harus menerapkan adaptor pemeriksaan nol selain enumerasi. Kode ini kemudian digandakan dalam berbagai penelepon, jadi mengapa tidak memasukkan adaptor ini ke dalam metode sehingga dapat digunakan kembali.
Penggunaan null yang valid untuk IEnumerable mungkin merupakan indikasi tidak adanya hasil, atau kegagalan operasi, tetapi dalam hal ini teknik lain harus dipertimbangkan, seperti melempar pengecualian.
sumber
Lihat di sini untuk badai kotoran rumit tentang
null
secara umum. Saya tidak setuju dengan pernyataan yangundefined
lainnull
, tetapi masih layak dibaca. Dan itu menjelaskan, mengapa Anda harus menghindarinull
sama sekali dan tidak hanya dalam kasus yang Anda tanyakan. Intinya,null
dalam bahasa apa pun ada kasus khusus. Anda harus memikirkannyanull
sebagai pengecualian.undefined
berbeda dalam hal itu, bahwa kode yang berurusan dengan perilaku tidak terdefinisi dalam kebanyakan kasus hanya bug. C dan sebagian besar bahasa lainnya juga memiliki perilaku yang tidak terdefinisi tetapi kebanyakan tidak memiliki pengidentifikasi untuk itu dalam bahasa tersebut.sumber
Dari perspektif mengelola kompleksitas, tujuan rekayasa perangkat lunak utama, kami ingin menghindari penyebaran kompleksitas siklomatik yang tidak perlu ke klien API. Mengembalikan nol ke klien sama seperti mengembalikan mereka biaya kompleksitas siklomatik dari cabang kode lain.
(Ini sesuai dengan beban pengujian unit. Anda harus menulis tes untuk kasus pengembalian nol, selain kasus pengembalian koleksi kosong.)
sumber