Jadi saya sering mengalami situasi ini ... di mana Do.Something(...)
mengembalikan koleksi nol, seperti:
int[] returnArray = Do.Something(...);
Lalu, saya mencoba menggunakan koleksi ini seperti ini:
foreach (int i in returnArray)
{
// do some more stuff
}
Saya hanya ingin tahu, mengapa loop foreach tidak dapat beroperasi pada koleksi nol? Tampaknya logis bagi saya bahwa 0 iterasi akan dieksekusi dengan koleksi nol ... alih-alih melempar a NullReferenceException
. Adakah yang tahu mengapa ini bisa terjadi?
Ini menjengkelkan karena saya bekerja dengan API yang tidak jelas persis apa yang mereka kembalikan, jadi saya berakhir di if (someCollection != null)
mana - mana ...
Sunting: Terima kasih semua karena menjelaskan foreach
kegunaan itu GetEnumerator
dan jika tidak ada enumerator yang mendapatkan, foreach akan gagal. Saya kira saya bertanya mengapa bahasa / runtime tidak bisa atau tidak akan melakukan pemeriksaan nol sebelum meraih enumerator. Tampak bagi saya bahwa perilaku itu masih akan didefinisikan dengan baik.
null
nilai. Apakah Anda menyarankan ini hanya untukforeach
perulangan atau pernyataan lain juga?Jawaban:
Baiklah, jawaban singkatnya adalah "karena memang itulah yang dirancang oleh perancang kompiler." Namun, secara realistis, objek koleksi Anda adalah nol, jadi tidak ada cara bagi kompiler untuk membuat enumerator untuk mengulangi koleksi.
Jika Anda benar-benar perlu melakukan sesuatu seperti ini, coba operator penggabungan nol:
sumber
GetEnumerator
hasilnyaSebuah
foreach
loop memanggilGetEnumerator
metode.Jika pengumpulannya adalah
null
, pemanggilan metode ini menghasilkan aNullReferenceException
.Merupakan praktik yang buruk untuk mengembalikan
null
koleksi; metode Anda harus mengembalikan koleksi kosong.sumber
int[] returnArray = Do.Something() ?? new int[] {};
... ?? new int[0]
.Ada perbedaan besar antara koleksi kosong dan referensi nol untuk koleksi.
Ketika Anda menggunakan
foreach
, secara internal, ini memanggil metode GetEnumerator () dari IEnumerable . Ketika referensi nol, ini akan memunculkan pengecualian ini.Namun, itu sangat sah untuk memiliki
IEnumerable
atauIEnumerable<T>
. Dalam hal ini, foreach tidak akan "beralih" pada apa pun (karena koleksinya kosong), tetapi juga tidak akan melempar, karena ini adalah skenario yang benar-benar valid.Edit:
Secara pribadi, jika Anda perlu mengatasinya, saya akan merekomendasikan metode ekstensi:
Anda kemudian dapat menghubungi:
sumber
Ini sedang dijawab lama tetapi saya telah mencoba melakukan ini dengan cara berikut untuk hanya menghindari pengecualian null pointer dan mungkin berguna bagi seseorang yang menggunakan operator cek C # null?
sumber
null
) menggeneralisasi seluruh loop ke LCDEnumerable
(seperti menggunakan??
), b) memerlukan penambahan Metode Perpanjangan untuk setiap Proyek, dan c) memerlukan penghindarannull
IEnumerable
(Pffft! Puh-LEAZE! SMH.) untuk memulainya.Metode ekstensi lain untuk mengatasi ini:
Konsumsi dalam beberapa cara:
(1) dengan metode yang menerima
T
:(2) dengan ekspresi:
(3) dengan metode anonim multiline
sumber
Console.WriteLine
hanyalah sebuah contoh metode yang mengambil satu argumen (anAction<T>
). Item 1, 2 dan 3 menunjukkan contoh fungsi yang lewat ke.ForEach
metode ekstensi.null
) menggeneralisasi seluruh loop ke LCDEnumerable
(seperti menggunakan??
akan ), b) memerlukan penambahan Metode Ekstensi untuk setiap Proyek, atau c) mengharuskan untuk menghindarinull
IEnumerable
s (Pffft! Puh-LEAZE! SMH.) untuk memulai dengan (cuz,null
berarti N / A, sedangkan daftar kosong berarti, aplikasi itu. tetapi saat ini, yah, kosong !, yaitu seorang Empl. dapat memiliki Komisi yang N / A untuk non-Penjualan atau kosong untuk Penjualan).Cukup tulis metode ekstensi untuk membantu Anda:
sumber
Karena koleksi nol tidak sama dengan koleksi kosong. Koleksi kosong adalah objek koleksi tanpa elemen; koleksi nol adalah objek yang tidak ada.
Ini ada sesuatu yang bisa dicoba: Nyatakan dua koleksi apa pun. Inisialisasi satu secara normal sehingga kosong, dan tetapkan nilainya yang lain
null
. Kemudian coba tambahkan objek ke kedua koleksi dan lihat apa yang terjadi.sumber
Itu adalah kesalahan
Do.Something()
. Praktik terbaik di sini adalah mengembalikan array ukuran 0 (itu mungkin) daripada nol.sumber
Karena di belakang layar yang
foreach
memperoleh enumerator, setara dengan ini:sumber
null
referensi, misalnya ketika mengakses anggota. Biasanya ini adalah kesalahan, dan jika tidak maka cukup sederhana untuk menangani ini misalnya dengan metode ekstensi yang diberikan pengguna lain sebagai jawaban.Saya pikir penjelasan mengapa pengecualian dilemparkan sangat jelas dengan jawaban yang diberikan di sini. Saya hanya ingin melengkapi dengan cara saya biasanya bekerja dengan koleksi ini. Karena, beberapa kali, saya menggunakan koleksi lebih dari sekali dan harus menguji apakah nol setiap kali. Untuk menghindarinya, saya melakukan hal berikut:
Dengan cara ini kita dapat menggunakan koleksi sebanyak yang kita inginkan tanpa takut pengecualian dan kita tidak mencemari kode dengan pernyataan kondisional berlebihan.
Menggunakan operator cek nol
?.
juga merupakan pendekatan yang bagus. Tetapi, dalam hal array (seperti contoh dalam pertanyaan), harus diubah menjadi Daftar sebelumnya:sumber
ForEach
metode adalah salah satu hal yang saya benci dalam basis kode.sumber