Ini adalah pertanyaan tambahan dari Access to Modified Closure . Saya hanya ingin memverifikasi apakah berikut ini sebenarnya cukup aman untuk penggunaan produksi.
List<string> lists = new List<string>();
//Code to retrieve lists from DB
foreach (string list in lists)
{
Button btn = new Button();
btn.Click += new EventHandler(delegate { MessageBox.Show(list); });
}
Saya hanya menjalankan di atas sekali per startup. Untuk saat ini tampaknya berfungsi dengan baik. Seperti yang telah disebutkan Jon tentang hasil yang berlawanan dengan intuisi dalam beberapa kasus. Jadi apa yang perlu saya waspadai di sini? Apakah akan baik-baik saja jika daftar dijalankan lebih dari sekali?
Jawaban:
Sebelum C # 5, Anda perlu mendeklarasikan ulang sebuah variabel di dalam foreach - jika tidak maka akan dibagikan, dan semua penangan Anda akan menggunakan string terakhir:
Secara signifikan, perhatikan bahwa dari C # 5 dan seterusnya, ini telah berubah, dan khususnya dalam kasus
foreach
, Anda tidak perlu melakukan ini lagi: kode dalam pertanyaan akan bekerja seperti yang diharapkan.Untuk menunjukkan bahwa ini tidak berfungsi tanpa perubahan ini, pertimbangkan hal berikut:
Jalankan cara di atas sebelum C # 5 , dan meskipun setiap tombol menunjukkan nama yang berbeda, mengklik tombol tersebut menunjukkan "Wilma" empat kali.
Ini karena spesifikasi bahasa (ECMA 334 v4, 15.8.4) (sebelum C # 5) mendefinisikan:
Perhatikan bahwa variabel
v
(yaitu milik Andalist
) dideklarasikan di luar perulangan. Jadi berdasarkan aturan variabel yang ditangkap, semua iterasi daftar akan berbagi pemegang variabel yang ditangkap.Dari C # 5 dan seterusnya, ini diubah: variabel iterasi (
v
) dicakup di dalam loop. Saya tidak memiliki referensi spesifikasi, tetapi pada dasarnya menjadi:Berhenti berlangganan kembali; jika Anda secara aktif ingin berhenti berlangganan penangan anonim, triknya adalah dengan menangkap penangan itu sendiri:
Demikian juga, jika Anda menginginkan penanganan kejadian sekali saja (seperti Muat dll):
Ini sekarang berhenti berlangganan sendiri ;-p
sumber
for
tidak berubah di 5.0